Mailing List Archive

race condition in popen2._test()
Hello,

I am compiling Python v1.52c1 on a Sun Ultra-4 and am failing the test on
popen2.py (this test was not included in earlier distributions):

taiyang:~/src/Python-1.5.2c1> ./python Lib/popen2.py
testing popen2...
testing popen3...
Traceback (innermost last):
File "Lib/popen2.py", line 99, in ?
_test()
File "Lib/popen2.py", line 95, in _test
assert not _active
AssertionError


Looking at the code in popen2.py:
92 assert r.read() == teststr
93 assert e.read() == ""
94 _cleanup()
95 assert not _active
96 print "All OK"


_active is a list of all the instances of Popen3. The _cleanup function
iterates through this list and polls each instance to see if it's done.

def _cleanup():
for inst in _active[:]:
inst.poll()


The poll function does a 'waitpid' on its child, and if it's exit status
is available, then it removes itself from the list.

def poll(self):
if self.sts < 0:
try:
pid, sts = os.waitpid(self.pid, os.WNOHANG)
if pid == self.pid:
self.sts = sts
_active.remove(self)
except os.error:
pass
return self.sts


I believe that the error I am seeing is because the child processes do not
have enough time to close before they're polled in _cleanup. If I insert
some code so that it pauses before _cleanup:

** import time

92 assert r.read() == teststr
93 assert e.read() == ""
** start = time.time()
** while time.time() < start + 0.1: pass
94 _cleanup()
95 assert not _active
96 print "All OK"

the exception goes away and I pass the tests. I would argue against this
going inside _cleanup because _cleanup is called every time a new pipe is
created.

Jeff