]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
Issue #17555: Fix ForkAwareThreadLock so that size of after fork
authorRichard Oudkerk <shibturn@gmail.com>
Wed, 17 Apr 2013 18:15:52 +0000 (19:15 +0100)
committerRichard Oudkerk <shibturn@gmail.com>
Wed, 17 Apr 2013 18:15:52 +0000 (19:15 +0100)
registry does not grow exponentially with generation of process.

Lib/multiprocessing/util.py
Lib/test/test_multiprocessing.py
Misc/NEWS

index 3ce480fc42002afb2bfbd048e90ff4b1c55d22da..d1b3d2e3e87f7c650898f25211942f30533607c2 100644 (file)
@@ -329,10 +329,13 @@ atexit.register(_exit_function)
 
 class ForkAwareThreadLock(object):
     def __init__(self):
+        self._reset()
+        register_after_fork(self, ForkAwareThreadLock._reset)
+
+    def _reset(self):
         self._lock = threading.Lock()
         self.acquire = self._lock.acquire
         self.release = self._lock.release
-        register_after_fork(self, ForkAwareThreadLock.__init__)
 
 class ForkAwareLocal(threading.local):
     def __init__(self):
index bdf4e622490332b63742e55bf3973f6e3f799f22..88663ef55bb2d53d661190fd62bd5f38751846ef 100644 (file)
@@ -2430,13 +2430,43 @@ class TestFlags(unittest.TestCase):
             [sys.executable, '-E', '-B', '-O', '-c', prog])
         child_flags, grandchild_flags = json.loads(data.decode('ascii'))
         self.assertEqual(child_flags, grandchild_flags)
+
+#
+# Issue #17555: ForkAwareThreadLock
+#
+
+class TestForkAwareThreadLock(unittest.TestCase):
+    # We recurisvely start processes.  Issue #17555 meant that the
+    # after fork registry would get duplicate entries for the same
+    # lock.  The size of the registry at generation n was ~2**n.
+
+    @classmethod
+    def child(cls, n, conn):
+        if n > 1:
+            p = multiprocessing.Process(target=cls.child, args=(n-1, conn))
+            p.start()
+            p.join()
+        else:
+            conn.send(len(util._afterfork_registry))
+        conn.close()
+
+    def test_lock(self):
+        r, w = multiprocessing.Pipe(False)
+        l = util.ForkAwareThreadLock()
+        old_size = len(util._afterfork_registry)
+        p = multiprocessing.Process(target=self.child, args=(5, w))
+        p.start()
+        new_size = r.recv()
+        p.join()
+        self.assertLessEqual(new_size, old_size)
+
 #
 #
 #
 
 testcases_other = [OtherTest, TestInvalidHandle, TestInitializers,
                    TestStdinBadfiledescriptor, TestTimeouts, TestNoForkBomb,
-                   TestFlags]
+                   TestFlags, TestForkAwareThreadLock]
 
 #
 #
index 5b4080ac6ab676e94072eed42480f2d63d41ab73..9c651d314178082fb2009e9e0e40d51398a50204 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -28,6 +28,9 @@ Core and Builtins
 Library
 -------
 
+- Issue #17555: Fix ForkAwareThreadLock so that size of after fork
+  registry does not grow exponentially with generation of process.
+
 - Issue #17710: Fix cPickle raising a SystemError on bogus input.
 
 - Issue #17341: Include the invalid name in the error messages from re about