]> granicus.if.org Git - python/commitdiff
bpo-35477: multiprocessing.Pool.__enter__() fails if called twice (GH-11134)
authorVictor Stinner <vstinner@redhat.com>
Thu, 13 Dec 2018 01:15:30 +0000 (02:15 +0100)
committerGitHub <noreply@github.com>
Thu, 13 Dec 2018 01:15:30 +0000 (02:15 +0100)
multiprocessing.Pool.__enter__() now fails if the pool is not
running: "with pool:" fails if used more than once.

Lib/multiprocessing/pool.py
Lib/test/_test_multiprocessing.py
Misc/NEWS.d/next/Library/2018-12-13-00-10-51.bpo-35477.hHyy06.rst [new file with mode: 0644]

index 2b3cc59a9ff8b4a177712906f8b748f2870d68b6..c0775418852dfcc9e7263cc788ca586b261ff6c4 100644 (file)
@@ -261,6 +261,10 @@ class Pool(object):
         self._quick_put = self._inqueue._writer.send
         self._quick_get = self._outqueue._reader.recv
 
+    def _check_running(self):
+        if self._state != RUN:
+            raise ValueError("Pool not running")
+
     def apply(self, func, args=(), kwds={}):
         '''
         Equivalent of `func(*args, **kwds)`.
@@ -306,8 +310,7 @@ class Pool(object):
         '''
         Equivalent of `map()` -- can be MUCH slower than `Pool.map()`.
         '''
-        if self._state != RUN:
-            raise ValueError("Pool not running")
+        self._check_running()
         if chunksize == 1:
             result = IMapIterator(self._cache)
             self._taskqueue.put(
@@ -336,8 +339,7 @@ class Pool(object):
         '''
         Like `imap()` method but ordering of results is arbitrary.
         '''
-        if self._state != RUN:
-            raise ValueError("Pool not running")
+        self._check_running()
         if chunksize == 1:
             result = IMapUnorderedIterator(self._cache)
             self._taskqueue.put(
@@ -366,8 +368,7 @@ class Pool(object):
         '''
         Asynchronous version of `apply()` method.
         '''
-        if self._state != RUN:
-            raise ValueError("Pool not running")
+        self._check_running()
         result = ApplyResult(self._cache, callback, error_callback)
         self._taskqueue.put(([(result._job, 0, func, args, kwds)], None))
         return result
@@ -385,8 +386,7 @@ class Pool(object):
         '''
         Helper function to implement map, starmap and their async counterparts.
         '''
-        if self._state != RUN:
-            raise ValueError("Pool not running")
+        self._check_running()
         if not hasattr(iterable, '__len__'):
             iterable = list(iterable)
 
@@ -625,6 +625,7 @@ class Pool(object):
                     p.join()
 
     def __enter__(self):
+        self._check_running()
         return self
 
     def __exit__(self, exc_type, exc_val, exc_tb):
index 0b0fe7c9b298009bfcf6020d81808b26549ae12d..a2dc53c8e4e677ced3f2e812d51d40d5a06341fb 100644 (file)
@@ -2561,6 +2561,22 @@ class _TestPool(BaseTestCase):
         # they were released too.
         self.assertEqual(CountedObject.n_instances, 0)
 
+    def test_enter(self):
+        if self.TYPE == 'manager':
+            self.skipTest("test not applicable to manager")
+
+        pool = self.Pool(1)
+        with pool:
+            pass
+            # call pool.terminate()
+        # pool is no longer running
+
+        with self.assertRaises(ValueError):
+            # bpo-35477: pool.__enter__() fails if the pool is not running
+            with pool:
+                pass
+        pool.join()
+
 
 def raising():
     raise KeyError("key")
diff --git a/Misc/NEWS.d/next/Library/2018-12-13-00-10-51.bpo-35477.hHyy06.rst b/Misc/NEWS.d/next/Library/2018-12-13-00-10-51.bpo-35477.hHyy06.rst
new file mode 100644 (file)
index 0000000..524df71
--- /dev/null
@@ -0,0 +1,2 @@
+:meth:`multiprocessing.Pool.__enter__` now fails if the pool is not running:
+``with pool:`` fails if used more than once.