diff options
author | Antoine Pitrou <pitrou@free.fr> | 2017-06-13 15:54:10 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-06-13 15:54:10 (GMT) |
commit | a0ecaab006849ade08fbcf8413fe1e92d9c8d71c (patch) | |
tree | d405de61a61dac3ccc4d75a0fadb0dab39c991a2 /Lib/multiprocessing/util.py | |
parent | d071a20f136547a490783fcfa969c6528025a6d2 (diff) | |
download | cpython-a0ecaab006849ade08fbcf8413fe1e92d9c8d71c.zip cpython-a0ecaab006849ade08fbcf8413fe1e92d9c8d71c.tar.gz cpython-a0ecaab006849ade08fbcf8413fe1e92d9c8d71c.tar.bz2 |
[3.5] bpo-24484: Avoid race condition in multiprocessing cleanup (GH-2159) (#2167)
* 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.
(cherry picked from commit 1eb6c0074d17f4fd425cacfdda893d65f5f77f0a)
Diffstat (limited to 'Lib/multiprocessing/util.py')
-rw-r--r-- | Lib/multiprocessing/util.py | 34 |
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() |