Preventing deadlock on subprocess.Popen.poll()

According to
http://docs.python.org/2/library/subprocess.html#subprocess.Popen.poll

Warning: This will deadlock when using stdout=PIPE and/or stderr=PIPE
and the child process generates enough output to a pipe such that it
blocks waiting for the OS pipe buffer to accept more data.
Use communicate() to avoid that.
We count consecutive iterations that do not have any output, and
only if it reaches a certain threshold, self.communicate() is run.
This commit is contained in:
Amir Pakdel 2013-12-08 15:55:23 -05:00
parent 92b37c37d6
commit e5d284ef36

View File

@ -208,13 +208,25 @@ class NonBlockingPopen(subprocess.Popen):
fcntl.fcntl(conn, fcntl.F_SETFL, flags) fcntl.fcntl(conn, fcntl.F_SETFL, flags)
def poll_and_read_until_finish(self): def poll_and_read_until_finish(self):
silent_iterations = 0
while self.poll() is None: while self.poll() is None:
if self.stdout is not None: if self.stdout is not None:
silent_iterations = 0
self.recv() self.recv()
if self.stderr is not None: if self.stderr is not None:
silent_iterations = 0
self.recv_err() self.recv_err()
silent_iterations += 1
if silent_iterations > 100:
silent_iterations = 0
(stdoutdata, stderrdata) = self.communicate()
if stdoutdata:
log.debug(stdoutdata)
if stderrdata:
log.error(stderrdata)
time.sleep(0.01) time.sleep(0.01)
def communicate(self, input=None): def communicate(self, input=None):