]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
bpo-39651: Fix asyncio proactor _write_to_self() (GH-22197)
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Sat, 12 Sep 2020 07:09:54 +0000 (00:09 -0700)
committerGitHub <noreply@github.com>
Sat, 12 Sep 2020 07:09:54 +0000 (00:09 -0700)
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@python.org>
Lib/asyncio/proactor_events.py
Lib/asyncio/selector_events.py
Misc/NEWS.d/next/Library/2020-09-11-12-38-55.bpo-39651.JMp9l2.rst [new file with mode: 0644]

index 54e4deb2c349cdcf93c04d2896db014356d84633..3e0a14f6f4224ab8833674449c082bb46e436959 100644 (file)
@@ -791,8 +791,17 @@ class BaseProactorEventLoop(base_events.BaseEventLoop):
             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 "
index a05cbb6bdd69dc624d83b807b9a39d91130a97fb..6ba307163e1f7679732b3ba4b965f2f2b36f67a6 100644 (file)
@@ -133,14 +133,16 @@ class BaseSelectorEventLoop(base_events.BaseEventLoop):
         # 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 (file)
index 0000000..78dcff1
--- /dev/null
@@ -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.