Issue #12040: Expose a new attribute sentinel on instances of

:class:`multiprocessing.Process`.  Also, fix Process.join() to not use
polling anymore, when given a timeout.
This commit is contained in:
Antoine Pitrou 2011-06-06 19:35:31 +02:00
parent f068ab8304
commit 176f07dadf
6 changed files with 108 additions and 14 deletions

View file

@ -101,10 +101,12 @@ else:
if sys.platform != 'win32':
import time
import select
exit = os._exit
duplicate = os.dup
close = os.close
_select = util._eintr_retry(select.select)
#
# We define a Popen class similar to the one from subprocess, but
@ -118,8 +120,12 @@ if sys.platform != 'win32':
sys.stderr.flush()
self.returncode = None
r, w = os.pipe()
self.sentinel = r
self.pid = os.fork()
if self.pid == 0:
os.close(r)
if 'random' in sys.modules:
import random
random.seed()
@ -128,6 +134,11 @@ if sys.platform != 'win32':
sys.stderr.flush()
os._exit(code)
# `w` will be closed when the child exits, at which point `r`
# will become ready for reading (using e.g. select()).
os.close(w)
util.Finalize(self, os.close, (r,))
def poll(self, flag=os.WNOHANG):
if self.returncode is None:
try:
@ -145,20 +156,14 @@ if sys.platform != 'win32':
return self.returncode
def wait(self, timeout=None):
if timeout is None:
return self.poll(0)
deadline = time.time() + timeout
delay = 0.0005
while 1:
res = self.poll()
if res is not None:
break
remaining = deadline - time.time()
if remaining <= 0:
break
delay = min(delay * 2, remaining, 0.05)
time.sleep(delay)
return res
if self.returncode is None:
if timeout is not None:
r = _select([self.sentinel], [], [], timeout)[0]
if not r:
return None
# This shouldn't block if select() returned successfully.
return self.poll(os.WNOHANG if timeout == 0.0 else 0)
return self.returncode
def terminate(self):
if self.returncode is None:
@ -258,6 +263,7 @@ else:
self.pid = pid
self.returncode = None
self._handle = hp
self.sentinel = int(hp)
# send information to child
prep_data = get_preparation_data(process_obj._name)