This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author Mike Lewis
Recipients Mike Lewis
Date 2018-02-08.09:11:06
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1518081067.06.0.467229070634.issue32795@psf.upfronthosting.co.za>
In-reply-to
Content
When using a timeout with check_output(), the call does not terminate unless the child process generates output after the timeout. Looking at the code, it appears there is a second call to communicate() after the timeout has happened, presumably to retrieve any remaining output. This call appears to hang until the child process generates output.

I have two test cases (for Python 2.7 / subprocess32 and Python 3 / subprocess respectively). They show the same behaviour, the Python 2.7 version has been reproduced on Ubuntu 16.04.3 and Centos 7 and the Python 3 version on Ubuntu 16.043.

Each test case has a first example where bash executes a long sleep before generating output and where the timeout is not respected, and a second example that generates output at intervals and the timeout is respected.

Relevant code also attached below for reference:

then = time.time()
print("Subprocess with idle stdout at timeout: start at {}".format(then))
try:
    output = subprocess.check_output(["bash", "-c",
                                        "echo Subcall; sleep 5; echo Done;"],
                                       stderr=subprocess.STDOUT, timeout=1)
    now = time.time()
    print("Finish at: {}, {:.0f} seconds".format(now, now-then))
    print(output)
except subprocess.TimeoutExpired as te:
    now = time.time()
    print("Timed out at: {}, {:.0f} seconds".format(now, now-then))

then = time.time()
print("Generating stdout from subprocess: start at ", then)
try:
    output = subprocess.check_output(["bash", "-c",
                                        "echo Subcall; for i in 1 2 3 4 5; do sleep 1; echo $i; done; echo Done;"],
                                       stderr=subprocess.STDOUT, timeout=1)
    now = time.time()
    print("Finish at: {}, {:.0f} seconds".format(now, now-then))
    print(output)
except subprocess.TimeoutExpired as te:
    now = time.time()
    print("Timed out at: {}, {:.0f} seconds".format(now, now-then))
History
Date User Action Args
2018-02-08 09:11:07Mike Lewissetrecipients: + Mike Lewis
2018-02-08 09:11:07Mike Lewissetmessageid: <1518081067.06.0.467229070634.issue32795@psf.upfronthosting.co.za>
2018-02-08 09:11:07Mike Lewislinkissue32795 messages
2018-02-08 09:11:06Mike Lewiscreate