This repository was archived by the owner on Apr 12, 2018. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
This repository was archived by the owner on Apr 12, 2018. It is now read-only.
Process.on_sigchld do not work when Process.join was called #6
Copy link
Copy link
Open
Labels
Description
There is a unexpected behavior when calling Process.join() at almost the same time the child process exits. I added the following test:
def test_process_on_exit_is_called(self):
from multiprocessing import Semaphore
sem = Semaphore(1)
process = Process(target=lambda *_: sem.acquire(),
on_exit=lambda *_: sem.release())
process.start(wait=True)
print('started')
process.join()
print('joined')
self.assertEquals(sem.get_value(), 1)
print('done')And added some debug strings in ProcessOpen.poll() and Process.on_sigchld():
class ProcessOpen...
def poll(self, flag=os.WNOHANG):
if self.returncode is None:
while True:
try:
print('poll::waitpid')
pid, sts = os.waitpid(self.pid, flag)
print('poll::waitpid done')
except os.error as e:
if e.errno == errno.EINTR:
print('poll::waitpid interrupted')
continue
# Child process not yet created. See #1731717
# e.errno == errno.ECHILD == 10
# or, child has already exited.
print('poll::waitpid OSError {}'.format(e))
return None
else:
break
if pid == self.pid:
if os.WIFSIGNALED(sts):
self.returncode = -os.WTERMSIG(sts)
else:
assert os.WIFEXITED(sts)
self.returncode = os.WEXITSTATUS(sts)
[...]
class Process...
def on_sigchld(self, signum, sigframe):
if self._child is not None and self._child.pid:
print('on_sigchld')
pid, status = os.waitpid(self._child.pid, os.WNOHANG)
if pid == self._child.pid:
self._exitcode = os.WEXITSTATUS(status)
print('on_exit')
if self._on_exit:
self._on_exit(self)
os.wait()
print('clean')
self.clean()When I execute the test, I get:
======================================================================
FAIL: test_process_on_exit_is_called (test_process.TestProcess)
----------------------------------------------------------------------
Traceback (most recent call last):
File "/home/greg/semio/src/projects/process-kit/tests/test_process.py", line 398, in test_process_on_exit_is_called
self.assertEquals(sem.get_value(), 1)
AssertionError: 0 != 1
-------------------- >> begin captured stdout << ---------------------
started
poll::waitpid
on_sigchld
poll::waitpid OSError [Errno 10] No child processes
joined
--------------------- >> end captured stdout << ----------------------It means that the parent process enters ProcessOpen.poll() and is interrupted by the SIGCHLD signal in os.waitpid(). The Process.on_sigchld() signal handler is executed. However when it evaluates os.waitpid(), it returns the execution back to the call of os.waitpid() inside ProcessOpen.poll(). Hence the remaining code of Process.on_sigchld() is never called.