Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 409c313

Browse files
committed
Issue #17555: Fix ForkAwareThreadLock so that size of after fork
registry does not grow exponentially with generation of process.
1 parent b38897f commit 409c313

3 files changed

Lines changed: 38 additions & 2 deletions

File tree

Lib/multiprocessing/util.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,10 +322,13 @@ def _exit_function(info=info, debug=debug, _run_finalizers=_run_finalizers,
322322

323323
class ForkAwareThreadLock(object):
324324
def __init__(self):
325+
self._reset()
326+
register_after_fork(self, ForkAwareThreadLock._reset)
327+
328+
def _reset(self):
325329
self._lock = threading.Lock()
326330
self.acquire = self._lock.acquire
327331
self.release = self._lock.release
328-
register_after_fork(self, ForkAwareThreadLock.__init__)
329332

330333
class ForkAwareLocal(threading.local):
331334
def __init__(self):

Lib/test/test_multiprocessing.py

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3431,13 +3431,43 @@ def test_noforkbomb(self):
34313431
self.assertEqual('123', out.decode('ascii').rstrip())
34323432
self.assertEqual('', err.decode('ascii'))
34333433

3434+
#
3435+
# Issue #17555: ForkAwareThreadLock
3436+
#
3437+
3438+
class TestForkAwareThreadLock(unittest.TestCase):
3439+
# We recurisvely start processes. Issue #17555 meant that the
3440+
# after fork registry would get duplicate entries for the same
3441+
# lock. The size of the registry at generation n was ~2**n.
3442+
3443+
@classmethod
3444+
def child(cls, n, conn):
3445+
if n > 1:
3446+
p = multiprocessing.Process(target=cls.child, args=(n-1, conn))
3447+
p.start()
3448+
p.join()
3449+
else:
3450+
conn.send(len(util._afterfork_registry))
3451+
conn.close()
3452+
3453+
def test_lock(self):
3454+
r, w = multiprocessing.Pipe(False)
3455+
l = util.ForkAwareThreadLock()
3456+
old_size = len(util._afterfork_registry)
3457+
p = multiprocessing.Process(target=self.child, args=(5, w))
3458+
p.start()
3459+
new_size = r.recv()
3460+
p.join()
3461+
self.assertLessEqual(new_size, old_size)
3462+
34343463
#
34353464
#
34363465
#
34373466

34383467
testcases_other = [OtherTest, TestInvalidHandle, TestInitializers,
34393468
TestStdinBadfiledescriptor, TestWait, TestInvalidFamily,
3440-
TestFlags, TestTimeouts, TestNoForkBomb]
3469+
TestFlags, TestTimeouts, TestNoForkBomb,
3470+
TestForkAwareThreadLock]
34413471

34423472
#
34433473
#

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ Core and Builtins
2929
Library
3030
-------
3131

32+
- Issue #17555: Fix ForkAwareThreadLock so that size of after fork
33+
registry does not grow exponentially with generation of process.
34+
3235
- Issue #17707: multiprocessing.Queue's get() method does not block for short
3336
timeouts.
3437

0 commit comments

Comments
 (0)