mirror of
https://github.com/python/cpython.git
synced 2025-08-04 00:48:58 +00:00
Add description of the deadlock problem with child processes and pipes, and
hints about how to work around it. Closes SF bug #530637.
This commit is contained in:
parent
a23b5739bb
commit
9ea01d415f
2 changed files with 67 additions and 0 deletions
|
@ -339,6 +339,11 @@ streams and also retrieve the return codes is to use the
|
|||
\class{Popen3} and \class{Popen4} classes from the \refmodule{popen2}
|
||||
module; these are only available on \UNIX.
|
||||
|
||||
For a discussion of possible dead lock conditions related to the use
|
||||
of these functions, see ``\ulink{Flow Control
|
||||
Issues}{popen2-flow-control.html}''
|
||||
(section~\ref{popen2-flow-control}).
|
||||
|
||||
\begin{funcdesc}{popen2}{cmd\optional{, mode\optional{, bufsize}}}
|
||||
Executes \var{cmd} as a sub-process. Returns the file objects
|
||||
\code{(\var{child_stdin}, \var{child_stdout})}.
|
||||
|
|
|
@ -114,3 +114,65 @@ This will always be \code{None} for \class{Popen4} instances.
|
|||
\begin{memberdesc}{pid}
|
||||
The process ID of the child process.
|
||||
\end{memberdesc}
|
||||
|
||||
|
||||
\subsection{Flow Control Issues \label{popen2-flow-control}}
|
||||
|
||||
Any time you are working with any form of inter-process communication,
|
||||
control flow needs to be carefully thought out. This remains the case
|
||||
with the file objects provided by this module (or the \refmodule{os}
|
||||
module equivalents).
|
||||
|
||||
% Example explanation and suggested work-arounds substantially stolen
|
||||
% from Martin von Löwis:
|
||||
% http://mail.python.org/pipermail/python-dev/2000-September/009460.html
|
||||
|
||||
When reading output from a child process that writes a lot of data to
|
||||
standard error while the parent is reading from the child's standard
|
||||
out, a dead lock can occur. A similar situation can occur with other
|
||||
combinations of reads and writes. The essential factors are that more
|
||||
than \constant{_PC_PIPE_BUF} bites are being written by one process in
|
||||
a blocking fashion, while the other process is reading from the other
|
||||
process, also in a blocking fashion.
|
||||
|
||||
There are several ways to deal with this situation.
|
||||
|
||||
The simplest application change, in many cases, will be to follow this
|
||||
model in the parent process:
|
||||
|
||||
\begin{verbatim}
|
||||
import popen2
|
||||
|
||||
r, w, e = popen2.popen3('python slave.py')
|
||||
e.readlines()
|
||||
r.readlines()
|
||||
r.close()
|
||||
e.close()
|
||||
w.close()
|
||||
\end{verbatim}
|
||||
|
||||
with code like this in the child:
|
||||
|
||||
\begin{verbatim}
|
||||
import os
|
||||
import sys
|
||||
|
||||
# note that each of these print statements
|
||||
# writes a single long string
|
||||
|
||||
print >>sys.stderr, 400 * 'this is a test\n'
|
||||
os.close(sys.stderr.fileno())
|
||||
print >>sys.stdout, 400 * 'this is another test\n'
|
||||
\end{verbatim}
|
||||
|
||||
In particular, note that \code{sys.stderr} must be closed after
|
||||
writing all data, or \method{readlines()} won't return. Also note
|
||||
that \function{os.close()} must be used, as \code{sys.stderr.close()}
|
||||
won't close \code{stderr} (otherwise assigning to \code{sys.stderr}
|
||||
will silently close it, so no further errors can be printed).
|
||||
|
||||
Applications which need to support a more general approach should
|
||||
integrate I/O over pipes with their \function{select()} loops, or use
|
||||
separate threads to read each of the individual files provided by
|
||||
whichever \function{popen*()} function or \class{Popen*} class was
|
||||
used.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue