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

Skip to content

Commit cca8c53

Browse files
committed
Issue #17097: Make multiprocessing ignore EINTR.
1 parent 8087879 commit cca8c53

3 files changed

Lines changed: 86 additions & 4 deletions

File tree

Lib/multiprocessing/connection.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,7 +366,10 @@ def _close(self, _close=os.close):
366366
def _send(self, buf, write=_write):
367367
remaining = len(buf)
368368
while True:
369-
n = write(self._handle, buf)
369+
try:
370+
n = write(self._handle, buf)
371+
except InterruptedError:
372+
continue
370373
remaining -= n
371374
if remaining == 0:
372375
break
@@ -377,7 +380,10 @@ def _recv(self, size, read=_read):
377380
handle = self._handle
378381
remaining = size
379382
while remaining > 0:
380-
chunk = read(handle, remaining)
383+
try:
384+
chunk = read(handle, remaining)
385+
except InterruptedError:
386+
continue
381387
n = len(chunk)
382388
if n == 0:
383389
if remaining == size:
@@ -581,7 +587,13 @@ def __init__(self, address, family, backlog=1):
581587
self._unlink = None
582588

583589
def accept(self):
584-
s, self._last_accepted = self._socket.accept()
590+
while True:
591+
try:
592+
s, self._last_accepted = self._socket.accept()
593+
except InterruptedError:
594+
pass
595+
else:
596+
break
585597
s.setblocking(True)
586598
return Connection(s.detach())
587599

Lib/test/test_multiprocessing.py

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3460,14 +3460,82 @@ def test_lock(self):
34603460
p.join()
34613461
self.assertLessEqual(new_size, old_size)
34623462

3463+
#
3464+
# Issue #17097: EINTR should be ignored by recv(), send(), accept() etc
3465+
#
3466+
3467+
class TestIgnoreEINTR(unittest.TestCase):
3468+
3469+
@classmethod
3470+
def _test_ignore(cls, conn):
3471+
def handler(signum, frame):
3472+
pass
3473+
signal.signal(signal.SIGUSR1, handler)
3474+
conn.send('ready')
3475+
x = conn.recv()
3476+
conn.send(x)
3477+
conn.send_bytes(b'x'*(1024*1024)) # sending 1 MB should block
3478+
3479+
@unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1')
3480+
def test_ignore(self):
3481+
conn, child_conn = multiprocessing.Pipe()
3482+
try:
3483+
p = multiprocessing.Process(target=self._test_ignore,
3484+
args=(child_conn,))
3485+
p.daemon = True
3486+
p.start()
3487+
child_conn.close()
3488+
self.assertEqual(conn.recv(), 'ready')
3489+
time.sleep(0.1)
3490+
os.kill(p.pid, signal.SIGUSR1)
3491+
time.sleep(0.1)
3492+
conn.send(1234)
3493+
self.assertEqual(conn.recv(), 1234)
3494+
time.sleep(0.1)
3495+
os.kill(p.pid, signal.SIGUSR1)
3496+
self.assertEqual(conn.recv_bytes(), b'x'*(1024*1024))
3497+
time.sleep(0.1)
3498+
p.join()
3499+
finally:
3500+
conn.close()
3501+
3502+
@classmethod
3503+
def _test_ignore_listener(cls, conn):
3504+
def handler(signum, frame):
3505+
pass
3506+
signal.signal(signal.SIGUSR1, handler)
3507+
l = multiprocessing.connection.Listener()
3508+
conn.send(l.address)
3509+
a = l.accept()
3510+
a.send('welcome')
3511+
3512+
@unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1')
3513+
def test_ignore_listener(self):
3514+
conn, child_conn = multiprocessing.Pipe()
3515+
try:
3516+
p = multiprocessing.Process(target=self._test_ignore_listener,
3517+
args=(child_conn,))
3518+
p.daemon = True
3519+
p.start()
3520+
child_conn.close()
3521+
address = conn.recv()
3522+
time.sleep(0.1)
3523+
os.kill(p.pid, signal.SIGUSR1)
3524+
time.sleep(0.1)
3525+
client = multiprocessing.connection.Client(address)
3526+
self.assertEqual(client.recv(), 'welcome')
3527+
p.join()
3528+
finally:
3529+
conn.close()
3530+
34633531
#
34643532
#
34653533
#
34663534

34673535
testcases_other = [OtherTest, TestInvalidHandle, TestInitializers,
34683536
TestStdinBadfiledescriptor, TestWait, TestInvalidFamily,
34693537
TestFlags, TestTimeouts, TestNoForkBomb,
3470-
TestForkAwareThreadLock]
3538+
TestForkAwareThreadLock, TestIgnoreEINTR]
34713539

34723540
#
34733541
#

Misc/NEWS

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ Core and Builtins
3838
Library
3939
-------
4040

41+
- Issue #17097: Make multiprocessing ignore EINTR.
42+
4143
- Issue #18339: Negative ints keys in unpickler.memo dict no longer cause a
4244
segfault inside the _pickle C extension.
4345

0 commit comments

Comments
 (0)