]> granicus.if.org Git - python/commitdiff
[3.5] bpo-30414: multiprocessing.Queue._feed do not break from main loop on exc ...
authorAntoine Pitrou <pitrou@free.fr>
Thu, 25 May 2017 15:19:10 +0000 (17:19 +0200)
committerGitHub <noreply@github.com>
Thu, 25 May 2017 15:19:10 +0000 (17:19 +0200)
* bpo-30414: multiprocesing.Queue._feed do not break from main loop on exc

Queue background running thread was not handling exceptions correctly.
Any exception occurred inside thread (putting unpickable object) cause
feeder to finish running. After that every message put into queue is
silently ignored.

* bpo-30414: multiprocesing.Queue._feed do not break from main loop on exc

Queue background running thread was not handling exceptions correctly.
Any exception occurred inside thread (putting unpickable object) cause
feeder to finish running. After that every message put into queue is
silently ignored.
(cherry picked from commit bc50f03db4f58c869b78e98468e374d7e61f1227)

Lib/multiprocessing/queues.py
Lib/test/_test_multiprocessing.py
Misc/NEWS

index 40ae10a88c1508c54e2cfd700dd8b4da5f6daaf8..2c888c00e7c29825a0abbb870380bcc4382dfc8a 100644 (file)
@@ -221,8 +221,8 @@ class Queue(object):
         else:
             wacquire = None
 
-        try:
-            while 1:
+        while 1:
+            try:
                 nacquire()
                 try:
                     if not buffer:
@@ -249,21 +249,19 @@ class Queue(object):
                                 wrelease()
                 except IndexError:
                     pass
-        except Exception as e:
-            if ignore_epipe and getattr(e, 'errno', 0) == errno.EPIPE:
-                return
-            # Since this runs in a daemon thread the resources it uses
-            # may be become unusable while the process is cleaning up.
-            # We ignore errors which happen after the process has
-            # started to cleanup.
-            try:
+            except Exception as e:
+                if ignore_epipe and getattr(e, 'errno', 0) == errno.EPIPE:
+                    return
+                # Since this runs in a daemon thread the resources it uses
+                # may be become unusable while the process is cleaning up.
+                # We ignore errors which happen after the process has
+                # started to cleanup.
                 if is_exiting():
                     info('error in queue thread: %s', e)
+                    return
                 else:
                     import traceback
                     traceback.print_exc()
-            except Exception:
-                pass
 
 _sentinel = object()
 
index 040212889486ec1b590f3032ddb972cff3707319..b24e7d6c32df1db5f852357ce8c2146b61a5351b 100644 (file)
@@ -752,6 +752,20 @@ class _TestQueue(BaseTestCase):
         # Windows (usually 15.6 ms)
         self.assertGreaterEqual(delta, 0.170)
 
+    def test_queue_feeder_donot_stop_onexc(self):
+        # bpo-30414: verify feeder handles exceptions correctly
+        if self.TYPE != 'processes':
+            self.skipTest('test not appropriate for {}'.format(self.TYPE))
+
+        class NotSerializable(object):
+            def __reduce__(self):
+                raise AttributeError
+        with test.support.captured_stderr():
+            q = self.Queue()
+            q.put(NotSerializable())
+            q.put(True)
+            self.assertTrue(q.get(timeout=0.1))
+
 #
 #
 #
index 23eed2a9b0f464ca86c526121fa7aec52d290d09..5aed87a30a72d45345500ad7a4b912404d6e6395 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -56,6 +56,9 @@ Extension Modules
 Library
 -------
 
+- bpo-30414: multiprocessing.Queue._feed background running
+  thread do not break from main loop on exception.
+
 - bpo-30003: Fix handling escape characters in HZ codec.  Based on patch
   by Ma Lin.