Problems with background processes on Windows
Gabriel Genellina
gagsl-py2 at yahoo.com.ar
Mon Mar 30 00:57:18 EDT 2009
Gabriel Genellina <gagsl-py2 <at> yahoo.com.ar> writes:
> En Sat, 28 Mar 2009 06:03:33 -0300, geoffbache <geoff.bache <at>
jeppesen.com>
> escribió:
> >
> > Well yes, but the point is surely that the standard output of the
> > background sleeping process is pointed to a different location? (you
> > can replace the null device with a file name of your choice and the
> > point is the same.) This process should not have any connection to the
> > standard output of sleep.py, and hence we shouldn't need to wait for
> > it to finish when collecting the standard output of sleep.py, surely?
> > (Even explicitly calling sys.stdout.close() in sleep.py doesn't seem
> > to help)
>
> Thesis: When the subprocess module creates the child process, it inherits
> the stdin/stdout/stderr handles from its parent (even if its own
> stdin/stdout/stderr are redirected; they're different). Until the
> grandchild process finishes, the grandparent stdout.read() won't return,
> because the pipe isn't closed until the last handle to it is closed.
I've confirmed the above description.
--- begin p0.py ---
import subprocess,os
p1 = subprocess.Popen(["python", "p1.py"],
stdout=subprocess.PIPE,
stderr=open(os.devnull, "wt"),
stdin=open(os.devnull))
print p1.communicate()
--- end p0.py ---
--- begin p1.py ---
import subprocess,sys,os,msvcrt
subprocess.Popen(
["python", "p2.py", str(msvcrt.get_osfhandle(sys.stdout.fileno()))],
stdout=open(os.devnull, "wt"),
stderr=open(os.devnull, "wt"),
stdin=open(os.devnull, "rt"))
print "exit p1.py"
--- end p1.py ---
--- begin p2.py ---
import sys, win32api, time, os
with open("p2.pid","wt") as f: f.write("%d" % os.getpid())
win32api.CloseHandle(int(sys.argv[1]))
time.sleep(30)
--- end p2.py ---
p2 has to close the inherited file handle corresponding to p1's stdout. Then,
when p1 itself finishes, the writing end of the pipe is actually closed and p0
can continue.
C:\TEMP\subp>python p0.py
('exit p1.py\r\n', None)
C:\TEMP\subp>type p2.pid
3018
C:\TEMP\subp>tasklist | find "python.exe"
python.exe 3018 0 4.304 KB
I'm unsure this could be considered a bug in subprocess - the documentation
says that parameter close_fds=True is not supported on Windows (so, the child
process inherits all open files, and this includes the parent's
stdin/stdout/stderr).
At the end, this is due to the fact that file handles 0, 1, 2 have no special
significance on Windows - it's the C runtime library which makes such things
special, not the OS.
More information about the Python-list
mailing list