Skip to content

Commit 2ad51c6

Browse files
miss-islingtonjxdabc
andauthoredJun 10, 2022
gh-90549: Fix leak of global named resources using multiprocessing spawn (GH-30617)
Co-authored-by: XD Trol <milestonejxd@gmail.com> Co-authored-by: Antoine Pitrou <pitrou@free.fr> (cherry picked from commit 30610d2) Co-authored-by: Leo Trol <milestone.jxd@gmail.com>
1 parent 8d8251a commit 2ad51c6

File tree

4 files changed

+54
-2
lines changed

4 files changed

+54
-2
lines changed
 

‎Lib/multiprocessing/context.py

+14
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,10 @@ class Process(process.BaseProcess):
223223
def _Popen(process_obj):
224224
return _default_context.get_context().Process._Popen(process_obj)
225225

226+
@staticmethod
227+
def _after_fork():
228+
return _default_context.get_context().Process._after_fork()
229+
226230
class DefaultContext(BaseContext):
227231
Process = Process
228232

@@ -283,6 +287,11 @@ def _Popen(process_obj):
283287
from .popen_spawn_posix import Popen
284288
return Popen(process_obj)
285289

290+
@staticmethod
291+
def _after_fork():
292+
# process is spawned, nothing to do
293+
pass
294+
286295
class ForkServerProcess(process.BaseProcess):
287296
_start_method = 'forkserver'
288297
@staticmethod
@@ -326,6 +335,11 @@ def _Popen(process_obj):
326335
from .popen_spawn_win32 import Popen
327336
return Popen(process_obj)
328337

338+
@staticmethod
339+
def _after_fork():
340+
# process is spawned, nothing to do
341+
pass
342+
329343
class SpawnContext(BaseContext):
330344
_name = 'spawn'
331345
Process = SpawnProcess

‎Lib/multiprocessing/process.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -304,8 +304,7 @@ def _bootstrap(self, parent_sentinel=None):
304304
if threading._HAVE_THREAD_NATIVE_ID:
305305
threading.main_thread()._set_native_id()
306306
try:
307-
util._finalizer_registry.clear()
308-
util._run_after_forkers()
307+
self._after_fork()
309308
finally:
310309
# delay finalization of the old process object until after
311310
# _run_after_forkers() is executed
@@ -336,6 +335,13 @@ def _bootstrap(self, parent_sentinel=None):
336335

337336
return exitcode
338337

338+
@staticmethod
339+
def _after_fork():
340+
from . import util
341+
util._finalizer_registry.clear()
342+
util._run_after_forkers()
343+
344+
339345
#
340346
# We subclass bytes to avoid accidental transmission of auth keys over network
341347
#

‎Lib/test/_test_multiprocessing.py

+30
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import unittest
66
import unittest.mock
77
import queue as pyqueue
8+
import textwrap
89
import time
910
import io
1011
import itertools
@@ -5699,6 +5700,35 @@ def test_namespace(self):
56995700
self.run_worker(self._test_namespace, o)
57005701

57015702

5703+
class TestNamedResource(unittest.TestCase):
5704+
def test_global_named_resource_spawn(self):
5705+
#
5706+
# gh-90549: Check that global named resources in main module
5707+
# will not leak by a subprocess, in spawn context.
5708+
#
5709+
testfn = os_helper.TESTFN
5710+
self.addCleanup(os_helper.unlink, testfn)
5711+
with open(testfn, 'w', encoding='utf-8') as f:
5712+
f.write(textwrap.dedent('''\
5713+
import multiprocessing as mp
5714+
5715+
ctx = mp.get_context('spawn')
5716+
5717+
global_resource = ctx.Semaphore()
5718+
5719+
def submain(): pass
5720+
5721+
if __name__ == '__main__':
5722+
p = ctx.Process(target=submain)
5723+
p.start()
5724+
p.join()
5725+
'''))
5726+
rc, out, err = test.support.script_helper.assert_python_ok(testfn)
5727+
# on error, err = 'UserWarning: resource_tracker: There appear to
5728+
# be 1 leaked semaphore objects to clean up at shutdown'
5729+
self.assertEqual(err, b'')
5730+
5731+
57025732
class MiscTestCase(unittest.TestCase):
57035733
def test__all__(self):
57045734
# Just make sure names in not_exported are excluded
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix a multiprocessing bug where a global named resource (such as a semaphore)
2+
could leak when a child process is spawned (as opposed to forked).

0 commit comments

Comments
 (0)
Please sign in to comment.