[Python-checkins] bpo-39651: Fix asyncio proactor _write_to_self() (GH-22197)
Miss Islington (bot)
webhook-mailer at python.org
Tue Sep 15 09:56:36 EDT 2020
https://github.com/python/cpython/commit/530d1105ed7b0aa5ef76e3116918fe39bc6a4823
commit: 530d1105ed7b0aa5ef76e3116918fe39bc6a4823
branch: 3.8
author: Miss Islington (bot) <31488909+miss-islington at users.noreply.github.com>
committer: GitHub <noreply at github.com>
date: 2020-09-12T00:09:54-07:00
summary:
bpo-39651: Fix asyncio proactor _write_to_self() (GH-22197)
Fix a race condition in the call_soon_threadsafe() method of
asyncio.ProactorEventLoop: do nothing if the self-pipe socket has
been closed.
(cherry picked from commit 1b0f0e3d7d03155da1cf9769a847874d559e57e3)
Co-authored-by: Victor Stinner <vstinner at python.org>
files:
A Misc/NEWS.d/next/Library/2020-09-11-12-38-55.bpo-39651.JMp9l2.rst
M Lib/asyncio/proactor_events.py
M Lib/asyncio/selector_events.py
diff --git a/Lib/asyncio/proactor_events.py b/Lib/asyncio/proactor_events.py
index 54e4deb2c349c..3e0a14f6f4224 100644
--- a/Lib/asyncio/proactor_events.py
+++ b/Lib/asyncio/proactor_events.py
@@ -791,8 +791,17 @@ def _loop_self_reading(self, f=None):
f.add_done_callback(self._loop_self_reading)
def _write_to_self(self):
+ # This may be called from a different thread, possibly after
+ # _close_self_pipe() has been called or even while it is
+ # running. Guard for self._csock being None or closed. When
+ # a socket is closed, send() raises OSError (with errno set to
+ # EBADF, but let's not rely on the exact error code).
+ csock = self._csock
+ if csock is None:
+ return
+
try:
- self._csock.send(b'\0')
+ csock.send(b'\0')
except OSError:
if self._debug:
logger.debug("Fail to write a null byte into the "
diff --git a/Lib/asyncio/selector_events.py b/Lib/asyncio/selector_events.py
index a05cbb6bdd69d..6ba307163e1f7 100644
--- a/Lib/asyncio/selector_events.py
+++ b/Lib/asyncio/selector_events.py
@@ -133,14 +133,16 @@ def _write_to_self(self):
# a socket is closed, send() raises OSError (with errno set to
# EBADF, but let's not rely on the exact error code).
csock = self._csock
- if csock is not None:
- try:
- csock.send(b'\0')
- except OSError:
- if self._debug:
- logger.debug("Fail to write a null byte into the "
- "self-pipe socket",
- exc_info=True)
+ if csock is None:
+ return
+
+ try:
+ csock.send(b'\0')
+ except OSError:
+ if self._debug:
+ logger.debug("Fail to write a null byte into the "
+ "self-pipe socket",
+ exc_info=True)
def _start_serving(self, protocol_factory, sock,
sslcontext=None, server=None, backlog=100,
diff --git a/Misc/NEWS.d/next/Library/2020-09-11-12-38-55.bpo-39651.JMp9l2.rst b/Misc/NEWS.d/next/Library/2020-09-11-12-38-55.bpo-39651.JMp9l2.rst
new file mode 100644
index 0000000000000..78dcff1370029
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2020-09-11-12-38-55.bpo-39651.JMp9l2.rst
@@ -0,0 +1,3 @@
+Fix a race condition in the ``call_soon_threadsafe()`` method of
+``asyncio.ProactorEventLoop``: do nothing if the self-pipe socket has been
+closed.
More information about the Python-checkins
mailing list