summaryrefslogtreecommitdiffstats
path: root/Lib/threading.py
diff options
context:
space:
mode:
authorKyle Stanley <aeros167@gmail.com>2020-03-27 19:31:22 (GMT)
committerGitHub <noreply@github.com>2020-03-27 19:31:22 (GMT)
commitb61b818d916942aad1f8f3e33181801c4a1ed14b (patch)
treee755041eb620f5b2937639b32c0b98d1afa54c89 /Lib/threading.py
parent5f9c131c099d6675d1a9d0228497865488afd548 (diff)
downloadcpython-b61b818d916942aad1f8f3e33181801c4a1ed14b.zip
cpython-b61b818d916942aad1f8f3e33181801c4a1ed14b.tar.gz
cpython-b61b818d916942aad1f8f3e33181801c4a1ed14b.tar.bz2
bpo-39812: Remove daemon threads in concurrent.futures (GH-19149)
Remove daemon threads from :mod:`concurrent.futures` by adding an internal `threading._register_atexit()`, which calls registered functions prior to joining all non-daemon threads. This allows for compatibility with subinterpreters, which don't support daemon threads.
Diffstat (limited to 'Lib/threading.py')
-rw-r--r--Lib/threading.py29
1 files changed, 29 insertions, 0 deletions
diff --git a/Lib/threading.py b/Lib/threading.py
index 46eb1b9..6b25e7a 100644
--- a/Lib/threading.py
+++ b/Lib/threading.py
@@ -3,6 +3,7 @@
import os as _os
import sys as _sys
import _thread
+import functools
from time import monotonic as _time
from _weakrefset import WeakSet
@@ -1346,6 +1347,27 @@ def enumerate():
with _active_limbo_lock:
return list(_active.values()) + list(_limbo.values())
+
+_threading_atexits = []
+_SHUTTING_DOWN = False
+
+def _register_atexit(func, *arg, **kwargs):
+ """CPython internal: register *func* to be called before joining threads.
+
+ The registered *func* is called with its arguments just before all
+ non-daemon threads are joined in `_shutdown()`. It provides a similar
+ purpose to `atexit.register()`, but its functions are called prior to
+ threading shutdown instead of interpreter shutdown.
+
+ For similarity to atexit, the registered functions are called in reverse.
+ """
+ if _SHUTTING_DOWN:
+ raise RuntimeError("can't register atexit after shutdown")
+
+ call = functools.partial(func, *arg, **kwargs)
+ _threading_atexits.append(call)
+
+
from _thread import stack_size
# Create the main thread object,
@@ -1367,6 +1389,8 @@ def _shutdown():
# _shutdown() was already called
return
+ global _SHUTTING_DOWN
+ _SHUTTING_DOWN = True
# Main thread
tlock = _main_thread._tstate_lock
# The main thread isn't finished yet, so its thread state lock can't have
@@ -1376,6 +1400,11 @@ def _shutdown():
tlock.release()
_main_thread._stop()
+ # Call registered threading atexit functions before threads are joined.
+ # Order is reversed, similar to atexit.
+ for atexit_call in reversed(_threading_atexits):
+ atexit_call()
+
# Join all non-deamon threads
while True:
with _shutdown_locks_lock: