Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 7aaa1ef

Browse files
committed
Issue #17018: Make Process.join() retry if os.waitpid() fails with EINTR.
1 parent 8fd3669 commit 7aaa1ef

3 files changed

Lines changed: 46 additions & 6 deletions

File tree

Lib/multiprocessing/forking.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
import os
3636
import sys
3737
import signal
38+
import errno
3839

3940
from multiprocessing import util, process
4041

@@ -128,12 +129,17 @@ def __init__(self, process_obj):
128129

129130
def poll(self, flag=os.WNOHANG):
130131
if self.returncode is None:
131-
try:
132-
pid, sts = os.waitpid(self.pid, flag)
133-
except os.error:
134-
# Child process not yet created. See #1731717
135-
# e.errno == errno.ECHILD == 10
136-
return None
132+
while True:
133+
try:
134+
pid, sts = os.waitpid(self.pid, flag)
135+
except os.error as e:
136+
if e.errno == errno.EINTR:
137+
continue
138+
# Child process not yet created. See #1731717
139+
# e.errno == errno.ECHILD == 10
140+
return None
141+
else:
142+
break
137143
if pid == self.pid:
138144
if os.WIFSIGNALED(sts):
139145
self.returncode = -os.WTERMSIG(sts)

Lib/test/test_multiprocessing.py

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2167,6 +2167,38 @@ def test_level(self):
21672167
# logger.warn('foo')
21682168
# assert self.__handled
21692169

2170+
#
2171+
# Check that Process.join() retries if os.waitpid() fails with EINTR
2172+
#
2173+
2174+
class _TestPollEintr(BaseTestCase):
2175+
2176+
ALLOWED_TYPES = ('processes',)
2177+
2178+
@classmethod
2179+
def _killer(cls, pid):
2180+
time.sleep(0.5)
2181+
os.kill(pid, signal.SIGUSR1)
2182+
2183+
@unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1')
2184+
def test_poll_eintr(self):
2185+
got_signal = [False]
2186+
def record(*args):
2187+
got_signal[0] = True
2188+
pid = os.getpid()
2189+
oldhandler = signal.signal(signal.SIGUSR1, record)
2190+
try:
2191+
killer = self.Process(target=self._killer, args=(pid,))
2192+
killer.start()
2193+
p = self.Process(target=time.sleep, args=(1,))
2194+
p.start()
2195+
p.join()
2196+
self.assertTrue(got_signal[0])
2197+
self.assertEqual(p.exitcode, 0)
2198+
killer.join()
2199+
finally:
2200+
signal.signal(signal.SIGUSR1, oldhandler)
2201+
21702202
#
21712203
# Test to verify handle verification, see issue 3321
21722204
#

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -230,6 +230,8 @@ Core and Builtins
230230
Library
231231
-------
232232

233+
- Issue #17018: Make Process.join() retry if os.waitpid() fails with EINTR.
234+
233235
- Issue #14720: sqlite3: Convert datetime microseconds correctly.
234236
Patch by Lowe Thiderman.
235237

0 commit comments

Comments
 (0)