summaryrefslogtreecommitdiffstats
path: root/Lib/multiprocessing
diff options
context:
space:
mode:
authorAntoine Pitrou <pitrou@free.fr>2017-06-13 15:10:39 (GMT)
committerGitHub <noreply@github.com>2017-06-13 15:10:39 (GMT)
commit1eb6c0074d17f4fd425cacfdda893d65f5f77f0a (patch)
tree11ecee463d518e10ddfbbd28e01f44dd13e3fb14 /Lib/multiprocessing
parent8323189ff1a19566f923c04b95e4d17fa57d1f56 (diff)
downloadcpython-1eb6c0074d17f4fd425cacfdda893d65f5f77f0a.zip
cpython-1eb6c0074d17f4fd425cacfdda893d65f5f77f0a.tar.gz
cpython-1eb6c0074d17f4fd425cacfdda893d65f5f77f0a.tar.bz2
bpo-24484: Avoid race condition in multiprocessing cleanup (#2159)
* bpo-24484: Avoid race condition in multiprocessing cleanup The finalizer registry can be mutated while inspected by multiprocessing at process exit. * Use test.support.start_threads() * Add Misc/NEWS
Diffstat (limited to 'Lib/multiprocessing')
-rw-r--r--Lib/multiprocessing/util.py34
1 files changed, 21 insertions, 13 deletions
diff --git a/Lib/multiprocessing/util.py b/Lib/multiprocessing/util.py
index 0ce274c..b490caa 100644
--- a/Lib/multiprocessing/util.py
+++ b/Lib/multiprocessing/util.py
@@ -241,20 +241,28 @@ def _run_finalizers(minpriority=None):
return
if minpriority is None:
- f = lambda p : p[0][0] is not None
+ f = lambda p : p[0] is not None
else:
- f = lambda p : p[0][0] is not None and p[0][0] >= minpriority
-
- items = [x for x in list(_finalizer_registry.items()) if f(x)]
- items.sort(reverse=True)
-
- for key, finalizer in items:
- sub_debug('calling %s', finalizer)
- try:
- finalizer()
- except Exception:
- import traceback
- traceback.print_exc()
+ f = lambda p : p[0] is not None and p[0] >= minpriority
+
+ # Careful: _finalizer_registry may be mutated while this function
+ # is running (either by a GC run or by another thread).
+
+ # list(_finalizer_registry) should be atomic, while
+ # list(_finalizer_registry.items()) is not.
+ keys = [key for key in list(_finalizer_registry) if f(key)]
+ keys.sort(reverse=True)
+
+ for key in keys:
+ finalizer = _finalizer_registry.get(key)
+ # key may have been removed from the registry
+ if finalizer is not None:
+ sub_debug('calling %s', finalizer)
+ try:
+ finalizer()
+ except Exception:
+ import traceback
+ traceback.print_exc()
if minpriority is None:
_finalizer_registry.clear()