Skip to content

Commit 5d0b3be

Browse files
committed
gh-71936: Fix race condition in multiprocessing.Pool
Proxes of shared objects register a Finalizer in BaseProxy._incref(), and it will call BaseProxy._decref() when it is GCed. This may cause a race condition with Pool(maxtasksperchild=None) on Windows. A connection will be closed and raised TypeError when a GC occurs between _ConnectionBase._check_writable() and _ConnectionBase._send_bytes() in _ConnectionBase.send() in the second or later task. Finalizers should be processed after each task is finished, because all proxies of shared objects will lost their references in the next task. Also, BaseProxy does not count references well.
1 parent 2fe44f7 commit 5d0b3be

File tree

3 files changed

+7
-4
lines changed

3 files changed

+7
-4
lines changed

Lib/multiprocessing/managers.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -850,20 +850,21 @@ def _incref(self):
850850
dispatch(conn, None, 'incref', (self._id,))
851851
util.debug('INCREF %r', self._token.id)
852852

853-
self._idset.add(self._id)
853+
refid = f'{self._id}.{id(self)}'
854+
self._idset.add(refid)
854855

855856
state = self._manager and self._manager._state
856857

857858
self._close = util.Finalize(
858859
self, BaseProxy._decref,
859-
args=(self._token, self._authkey, state,
860+
args=(self._token, refid, self._authkey, state,
860861
self._tls, self._idset, self._Client),
861862
exitpriority=10
862863
)
863864

864865
@staticmethod
865-
def _decref(token, authkey, state, tls, idset, _Client):
866-
idset.discard(token.id)
866+
def _decref(token, refid, authkey, state, tls, idset, _Client):
867+
idset.discard(refid)
867868

868869
# check whether manager is still alive
869870
if state is None or state.value == State.STARTED:

Lib/multiprocessing/pool.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,7 @@ def worker(inqueue, outqueue, initializer=None, initargs=(), maxtasks=None,
136136
put((job, i, (False, wrapped)))
137137

138138
task = job = result = func = args = kwds = None
139+
util._run_finalizers()
139140
completed += 1
140141
util.debug('worker exiting after %d tasks' % completed)
141142

Misc/ACKS

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ Larry Hastings
706706
Tim Hatch
707707
Zac Hatfield-Dodds
708708
Shane Hathaway
709+
Akinori Hattori
709710
Michael Haubenwallner
710711
Janko Hauser
711712
Flavian Hautbois

0 commit comments

Comments
 (0)