Issue #17097: Merge.
This commit is contained in:
commit
626032ac54
|
@ -363,7 +363,10 @@ class Connection(_ConnectionBase):
|
||||||
def _send(self, buf, write=_write):
|
def _send(self, buf, write=_write):
|
||||||
remaining = len(buf)
|
remaining = len(buf)
|
||||||
while True:
|
while True:
|
||||||
n = write(self._handle, buf)
|
try:
|
||||||
|
n = write(self._handle, buf)
|
||||||
|
except InterruptedError:
|
||||||
|
continue
|
||||||
remaining -= n
|
remaining -= n
|
||||||
if remaining == 0:
|
if remaining == 0:
|
||||||
break
|
break
|
||||||
|
@ -374,7 +377,10 @@ class Connection(_ConnectionBase):
|
||||||
handle = self._handle
|
handle = self._handle
|
||||||
remaining = size
|
remaining = size
|
||||||
while remaining > 0:
|
while remaining > 0:
|
||||||
chunk = read(handle, remaining)
|
try:
|
||||||
|
chunk = read(handle, remaining)
|
||||||
|
except InterruptedError:
|
||||||
|
continue
|
||||||
n = len(chunk)
|
n = len(chunk)
|
||||||
if n == 0:
|
if n == 0:
|
||||||
if remaining == size:
|
if remaining == size:
|
||||||
|
@ -578,7 +584,13 @@ class SocketListener(object):
|
||||||
self._unlink = None
|
self._unlink = None
|
||||||
|
|
||||||
def accept(self):
|
def accept(self):
|
||||||
s, self._last_accepted = self._socket.accept()
|
while True:
|
||||||
|
try:
|
||||||
|
s, self._last_accepted = self._socket.accept()
|
||||||
|
except InterruptedError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
break
|
||||||
s.setblocking(True)
|
s.setblocking(True)
|
||||||
return Connection(s.detach())
|
return Connection(s.detach())
|
||||||
|
|
||||||
|
|
|
@ -3513,6 +3513,74 @@ class TestForkAwareThreadLock(unittest.TestCase):
|
||||||
p.join()
|
p.join()
|
||||||
self.assertLessEqual(new_size, old_size)
|
self.assertLessEqual(new_size, old_size)
|
||||||
|
|
||||||
|
#
|
||||||
|
# Issue #17097: EINTR should be ignored by recv(), send(), accept() etc
|
||||||
|
#
|
||||||
|
|
||||||
|
class TestIgnoreEINTR(unittest.TestCase):
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _test_ignore(cls, conn):
|
||||||
|
def handler(signum, frame):
|
||||||
|
pass
|
||||||
|
signal.signal(signal.SIGUSR1, handler)
|
||||||
|
conn.send('ready')
|
||||||
|
x = conn.recv()
|
||||||
|
conn.send(x)
|
||||||
|
conn.send_bytes(b'x'*(1024*1024)) # sending 1 MB should block
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1')
|
||||||
|
def test_ignore(self):
|
||||||
|
conn, child_conn = multiprocessing.Pipe()
|
||||||
|
try:
|
||||||
|
p = multiprocessing.Process(target=self._test_ignore,
|
||||||
|
args=(child_conn,))
|
||||||
|
p.daemon = True
|
||||||
|
p.start()
|
||||||
|
child_conn.close()
|
||||||
|
self.assertEqual(conn.recv(), 'ready')
|
||||||
|
time.sleep(0.1)
|
||||||
|
os.kill(p.pid, signal.SIGUSR1)
|
||||||
|
time.sleep(0.1)
|
||||||
|
conn.send(1234)
|
||||||
|
self.assertEqual(conn.recv(), 1234)
|
||||||
|
time.sleep(0.1)
|
||||||
|
os.kill(p.pid, signal.SIGUSR1)
|
||||||
|
self.assertEqual(conn.recv_bytes(), b'x'*(1024*1024))
|
||||||
|
time.sleep(0.1)
|
||||||
|
p.join()
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _test_ignore_listener(cls, conn):
|
||||||
|
def handler(signum, frame):
|
||||||
|
pass
|
||||||
|
signal.signal(signal.SIGUSR1, handler)
|
||||||
|
l = multiprocessing.connection.Listener()
|
||||||
|
conn.send(l.address)
|
||||||
|
a = l.accept()
|
||||||
|
a.send('welcome')
|
||||||
|
|
||||||
|
@unittest.skipUnless(hasattr(signal, 'SIGUSR1'), 'requires SIGUSR1')
|
||||||
|
def test_ignore_listener(self):
|
||||||
|
conn, child_conn = multiprocessing.Pipe()
|
||||||
|
try:
|
||||||
|
p = multiprocessing.Process(target=self._test_ignore_listener,
|
||||||
|
args=(child_conn,))
|
||||||
|
p.daemon = True
|
||||||
|
p.start()
|
||||||
|
child_conn.close()
|
||||||
|
address = conn.recv()
|
||||||
|
time.sleep(0.1)
|
||||||
|
os.kill(p.pid, signal.SIGUSR1)
|
||||||
|
time.sleep(0.1)
|
||||||
|
client = multiprocessing.connection.Client(address)
|
||||||
|
self.assertEqual(client.recv(), 'welcome')
|
||||||
|
p.join()
|
||||||
|
finally:
|
||||||
|
conn.close()
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
@ -3520,7 +3588,7 @@ class TestForkAwareThreadLock(unittest.TestCase):
|
||||||
testcases_other = [OtherTest, TestInvalidHandle, TestInitializers,
|
testcases_other = [OtherTest, TestInvalidHandle, TestInitializers,
|
||||||
TestStdinBadfiledescriptor, TestWait, TestInvalidFamily,
|
TestStdinBadfiledescriptor, TestWait, TestInvalidFamily,
|
||||||
TestFlags, TestTimeouts, TestNoForkBomb,
|
TestFlags, TestTimeouts, TestNoForkBomb,
|
||||||
TestForkAwareThreadLock]
|
TestForkAwareThreadLock, TestIgnoreEINTR]
|
||||||
|
|
||||||
#
|
#
|
||||||
#
|
#
|
||||||
|
|
|
@ -135,6 +135,8 @@ Core and Builtins
|
||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue #17097: Make multiprocessing ignore EINTR.
|
||||||
|
|
||||||
- Issue #18339: Negative ints keys in unpickler.memo dict no longer cause a
|
- Issue #18339: Negative ints keys in unpickler.memo dict no longer cause a
|
||||||
segfault inside the _pickle C extension.
|
segfault inside the _pickle C extension.
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue