summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>2023-01-13 21:57:52 (GMT)
committerGitHub <noreply@github.com>2023-01-13 21:57:52 (GMT)
commit94f9198f58371ee0dc93e874b685545dcbd55eac (patch)
treec9da3658085ae21149207338fd510663ef3984cb
parent87f9b1d53f12538c579598304105974378677012 (diff)
downloadcpython-94f9198f58371ee0dc93e874b685545dcbd55eac.zip
cpython-94f9198f58371ee0dc93e874b685545dcbd55eac.tar.gz
cpython-94f9198f58371ee0dc93e874b685545dcbd55eac.tar.bz2
[3.10] GH-100573: Fix server hang caused by os.stat() on named pipe (Windows) (GH-100959) (#101020)
(cherry picked from commit 1bc7a736837272b15ad3a7aa472977bc720d1033)
-rw-r--r--Lib/asyncio/windows_events.py5
-rw-r--r--Lib/test/test_asyncio/test_windows_events.py40
-rw-r--r--Misc/NEWS.d/next/Library/2023-01-12-01-18-13.gh-issue-100573.KDskqo.rst1
3 files changed, 46 insertions, 0 deletions
diff --git a/Lib/asyncio/windows_events.py b/Lib/asyncio/windows_events.py
index ed1cd19..3204c7c 100644
--- a/Lib/asyncio/windows_events.py
+++ b/Lib/asyncio/windows_events.py
@@ -366,6 +366,10 @@ class ProactorEventLoop(proactor_events.BaseProactorEventLoop):
return
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:
if pipe and pipe.fileno() != -1:
self.call_exception_handler({
@@ -377,6 +381,7 @@ class ProactorEventLoop(proactor_events.BaseProactorEventLoop):
elif self._debug:
logger.warning("Accept pipe failed on pipe %r",
pipe, exc_info=True)
+ self.call_soon(loop_accept_pipe)
except exceptions.CancelledError:
if pipe:
pipe.close()
diff --git a/Lib/test/test_asyncio/test_windows_events.py b/Lib/test/test_asyncio/test_windows_events.py
index afd3028..46eb7ec 100644
--- a/Lib/test/test_asyncio/test_windows_events.py
+++ b/Lib/test/test_asyncio/test_windows_events.py
@@ -250,6 +250,46 @@ class ProactorTests(test_utils.TestCase):
proactor.sendto(sock, b'abc', addr=bad_address)
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):
diff --git a/Misc/NEWS.d/next/Library/2023-01-12-01-18-13.gh-issue-100573.KDskqo.rst b/Misc/NEWS.d/next/Library/2023-01-12-01-18-13.gh-issue-100573.KDskqo.rst
new file mode 100644
index 0000000..97b95d1
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2023-01-12-01-18-13.gh-issue-100573.KDskqo.rst
@@ -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.