Louis-Dominique Dubeau <[EMAIL PROTECTED]> added the comment:

I'm running python 2.5.2 on Ubuntu 8.10.

I believe I've also encountered the problem reported here.  The scenario
in my case was the following:

1. Python process A uses subprocess.Popen to create another python
process (B).  Process B is created with stdout=PIPE and stderr=PIPE.
Process A communicates with process B using communicate().

2. Python process B, starts a ssh process (process C) which is invoked
to open a new control socket in master mode.  Process C is started
without pipes so it gets its std{in,out,err} from process B.  Process C
is going to run for a long time.  That is, it will run until a command
is sent to the control socket to close the ssh connexion.

3. Process B does not wait for process C to end, so it ends right away.

4. Python process A remains stuck in communicate() until process C (ssh)
dies even though process B has ended already.

Analysis:

The reason for this is that process C (ssh) gets its stdout and stderr
from process B.  But process C keeps both stdout and stderr opened until
it is terminated.  So process A does not get an EOF on the pipes it
opened for communicating with process B until process C ends.

The set of conditions which will trigger the effect is not outlandish.
However, it is specific enough that testing by executing "pwd" or "ls
-l", or "echo blah" or any other simple command won't trigger it.

In my case, I fixed the problem by changing the code of process B to
invoke process C with stdout and stderr set to PIPE and close those
pipes as soon as process B is satisfied that process C is started
properly.  In this way, process A does not block.

(FYI, process A in my case is the python testing tool nosetests.  I use
nosetests to test a backup script written in python and that script
invokes ssh.)

It seems that in general subprocess creators might have two needs:

1. Create a subprocess and communicate with it until there is no more
data to be passed to its stdin or data to be read from its std{out,err}.

2. Create a subprocess and communicate with it *only* until *this*
process dies.  After it is dead, neither stdout nor stderr are of any
interest.

Currently, need 1 is addressed by communicate() but not need 2.  In my
scenario above, I was able to work around the problem by modifying
process B but there are going to be cases where process B is not
modifiable (or at least not easily modifiable).  In those cases, process
A has to be able to handle it.

----------
nosy: +lemur

_______________________________________
Python tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue4216>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to