mirror of
https://github.com/python/cpython.git
synced 2025-08-31 14:07:50 +00:00
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:
parent
f068ab8304
commit
176f07dadf
6 changed files with 108 additions and 14 deletions
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue