mirror of
https://github.com/python/cpython.git
synced 2025-09-27 10:50:04 +00:00
GH-100573: Fix server hang caused by os.stat() on named pipe (Windows) (#100959)
This commit is contained in:
parent
c00eb1eae6
commit
1bc7a73683
3 changed files with 46 additions and 0 deletions
|
@ -366,6 +366,10 @@ class ProactorEventLoop(proactor_events.BaseProactorEventLoop):
|
||||||
return
|
return
|
||||||
|
|
||||||
f = self._proactor.accept_pipe(pipe)
|
f = self._proactor.accept_pipe(pipe)
|
||||||
|
except BrokenPipeError:
|
||||||
|
if pipe and pipe.fileno() != -1:
|
||||||
|
pipe.close()
|
||||||
|
self.call_soon(loop_accept_pipe)
|
||||||
except OSError as exc:
|
except OSError as exc:
|
||||||
if pipe and pipe.fileno() != -1:
|
if pipe and pipe.fileno() != -1:
|
||||||
self.call_exception_handler({
|
self.call_exception_handler({
|
||||||
|
@ -377,6 +381,7 @@ class ProactorEventLoop(proactor_events.BaseProactorEventLoop):
|
||||||
elif self._debug:
|
elif self._debug:
|
||||||
logger.warning("Accept pipe failed on pipe %r",
|
logger.warning("Accept pipe failed on pipe %r",
|
||||||
pipe, exc_info=True)
|
pipe, exc_info=True)
|
||||||
|
self.call_soon(loop_accept_pipe)
|
||||||
except exceptions.CancelledError:
|
except exceptions.CancelledError:
|
||||||
if pipe:
|
if pipe:
|
||||||
pipe.close()
|
pipe.close()
|
||||||
|
|
|
@ -250,6 +250,46 @@ class ProactorTests(test_utils.TestCase):
|
||||||
proactor.sendto(sock, b'abc', addr=bad_address)
|
proactor.sendto(sock, b'abc', addr=bad_address)
|
||||||
sock.close()
|
sock.close()
|
||||||
|
|
||||||
|
def test_client_pipe_stat(self):
|
||||||
|
res = self.loop.run_until_complete(self._test_client_pipe_stat())
|
||||||
|
self.assertEqual(res, 'done')
|
||||||
|
|
||||||
|
async def _test_client_pipe_stat(self):
|
||||||
|
# Regression test for https://github.com/python/cpython/issues/100573
|
||||||
|
ADDRESS = r'\\.\pipe\test_client_pipe_stat-%s' % os.getpid()
|
||||||
|
|
||||||
|
async def probe():
|
||||||
|
# See https://github.com/python/cpython/pull/100959#discussion_r1068533658
|
||||||
|
h = _overlapped.ConnectPipe(ADDRESS)
|
||||||
|
try:
|
||||||
|
_winapi.CloseHandle(_overlapped.ConnectPipe(ADDRESS))
|
||||||
|
except OSError as e:
|
||||||
|
if e.winerror != _overlapped.ERROR_PIPE_BUSY:
|
||||||
|
raise
|
||||||
|
finally:
|
||||||
|
_winapi.CloseHandle(h)
|
||||||
|
|
||||||
|
with self.assertRaises(FileNotFoundError):
|
||||||
|
await probe()
|
||||||
|
|
||||||
|
[server] = await self.loop.start_serving_pipe(asyncio.Protocol, ADDRESS)
|
||||||
|
self.assertIsInstance(server, windows_events.PipeServer)
|
||||||
|
|
||||||
|
errors = []
|
||||||
|
self.loop.set_exception_handler(lambda _, data: errors.append(data))
|
||||||
|
|
||||||
|
for i in range(5):
|
||||||
|
await self.loop.create_task(probe())
|
||||||
|
|
||||||
|
self.assertEqual(len(errors), 0, errors)
|
||||||
|
|
||||||
|
server.close()
|
||||||
|
|
||||||
|
with self.assertRaises(FileNotFoundError):
|
||||||
|
await probe()
|
||||||
|
|
||||||
|
return "done"
|
||||||
|
|
||||||
|
|
||||||
class WinPolicyTests(test_utils.TestCase):
|
class WinPolicyTests(test_utils.TestCase):
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix a Windows :mod:`asyncio` bug with named pipes where a client doing ``os.stat()`` on the pipe would cause an error in the server that disabled serving future requests.
|
Loading…
Add table
Add a link
Reference in a new issue