[Python-checkins] cpython (merge 3.3 -> default): Issue #17555: Fix ForkAwareThreadLock so that size of after fork

richard.oudkerk python-checkins at python.org
Wed Apr 17 22:29:19 CEST 2013


http://hg.python.org/cpython/rev/2c350a75ff43
changeset:   83429:2c350a75ff43
parent:      83424:33a01f79a73e
parent:      83428:21314f27a40c
user:        Richard Oudkerk <shibturn at gmail.com>
date:        Wed Apr 17 21:09:38 2013 +0100
summary:
  Issue #17555: Fix ForkAwareThreadLock so that size of after fork
registry does not grow exponentially with generation of process.

files:
  Lib/multiprocessing/util.py      |   5 ++-
  Lib/test/test_multiprocessing.py |  32 +++++++++++++++++++-
  Misc/NEWS                        |   3 +
  3 files changed, 38 insertions(+), 2 deletions(-)


diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py
--- a/Lib/multiprocessing/util.py
+++ b/Lib/multiprocessing/util.py
@@ -322,10 +322,13 @@
 
 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):
diff --git a/Lib/test/test_multiprocessing.py b/Lib/test/test_multiprocessing.py
--- a/Lib/test/test_multiprocessing.py
+++ b/Lib/test/test_multiprocessing.py
@@ -3456,12 +3456,42 @@
             self.assertEqual('', err.decode('ascii'))
 
 #
+# 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, TestWait, TestInvalidFamily,
-                   TestFlags, TestTimeouts, TestNoForkBomb]
+                   TestFlags, TestTimeouts, TestNoForkBomb,
+                   TestForkAwareThreadLock]
 
 #
 #
diff --git a/Misc/NEWS b/Misc/NEWS
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -42,6 +42,9 @@
 Library
 -------
 
+- Issue #17555: Fix ForkAwareThreadLock so that size of after fork
+  registry does not grow exponentially with generation of process.
+
 - Issue #17707: multiprocessing.Queue's get() method does not block for short
   timeouts.
 

-- 
Repository URL: http://hg.python.org/cpython


More information about the Python-checkins mailing list