mirror of
https://github.com/python/cpython.git
synced 2025-11-02 11:08:57 +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}
|
\class{Popen3} and \class{Popen4} classes from the \refmodule{popen2}
|
||||||
module; these are only available on \UNIX.
|
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}}}
|
\begin{funcdesc}{popen2}{cmd\optional{, mode\optional{, bufsize}}}
|
||||||
Executes \var{cmd} as a sub-process. Returns the file objects
|
Executes \var{cmd} as a sub-process. Returns the file objects
|
||||||
\code{(\var{child_stdin}, \var{child_stdout})}.
|
\code{(\var{child_stdin}, \var{child_stdout})}.
|
||||||
|
|
|
||||||
|
|
@ -114,3 +114,65 @@ This will always be \code{None} for \class{Popen4} instances.
|
||||||
\begin{memberdesc}{pid}
|
\begin{memberdesc}{pid}
|
||||||
The process ID of the child process.
|
The process ID of the child process.
|
||||||
\end{memberdesc}
|
\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