Skip to content

Commit 14d5331

Browse files
authored
bpo-40234: Revert "bpo-37266: Daemon threads are now denied in subinterpreters (GH-14049)" (GH-19456)
This reverts commit 066e5b1.
1 parent 909b87d commit 14d5331

7 files changed

Lines changed: 21 additions & 91 deletions

File tree

Doc/library/threading.rst

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -280,8 +280,6 @@ since it is impossible to detect the termination of alien threads.
280280
base class constructor (``Thread.__init__()``) before doing anything else to
281281
the thread.
282282

283-
Daemon threads must not be used in subinterpreters.
284-
285283
.. versionchanged:: 3.3
286284
Added the *daemon* argument.
287285

@@ -296,12 +294,6 @@ since it is impossible to detect the termination of alien threads.
296294
This method will raise a :exc:`RuntimeError` if called more than once
297295
on the same thread object.
298296

299-
Raise a :exc:`RuntimeError` if the thread is a daemon thread and the
300-
method is called from a subinterpreter.
301-
302-
.. versionchanged:: 3.9
303-
In a subinterpreter, spawning a daemon thread now raises an exception.
304-
305297
.. method:: run()
306298

307299
Method representing the thread's activity.

Doc/whatsnew/3.9.rst

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -369,15 +369,6 @@ The :mod:`socket` module now exports the :data:`~socket.CAN_RAW_JOIN_FILTERS`
369369
constant on Linux 4.1 and greater.
370370
(Contributed by Stefan Tatschner and Zackery Spytz in :issue:`25780`.)
371371

372-
threading
373-
---------
374-
375-
In a subinterpreter, spawning a daemon thread now raises a :exc:`RuntimeError`. Daemon
376-
threads were never supported in subinterpreters. Previously, the subinterpreter
377-
finalization crashed with a Python fatal error if a daemon thread was still
378-
running.
379-
(Contributed by Victor Stinner in :issue:`37266`.)
380-
381372
sys
382373
---
383374

Lib/test/test_threading.py

Lines changed: 19 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1022,32 +1022,28 @@ def f():
10221022
# The thread was joined properly.
10231023
self.assertEqual(os.read(r, 1), b"x")
10241024

1025-
def test_daemon_thread(self):
1026-
r, w = self.pipe()
1027-
code = textwrap.dedent(f"""
1025+
@cpython_only
1026+
def test_daemon_threads_fatal_error(self):
1027+
subinterp_code = f"""if 1:
1028+
import os
10281029
import threading
1029-
import sys
1030-
1031-
channel = open({w}, "w", closefd=False)
1032-
1033-
def func():
1034-
pass
1030+
import time
10351031
1036-
thread = threading.Thread(target=func, daemon=True)
1037-
try:
1038-
thread.start()
1039-
except RuntimeError as exc:
1040-
print("ok: %s" % exc, file=channel, flush=True)
1041-
else:
1042-
thread.join()
1043-
print("fail: RuntimeError not raised", file=channel, flush=True)
1044-
""")
1045-
ret = test.support.run_in_subinterp(code)
1046-
self.assertEqual(ret, 0)
1032+
def f():
1033+
# Make sure the daemon thread is still running when
1034+
# Py_EndInterpreter is called.
1035+
time.sleep({test.support.SHORT_TIMEOUT})
1036+
threading.Thread(target=f, daemon=True).start()
1037+
"""
1038+
script = r"""if 1:
1039+
import _testcapi
10471040
1048-
msg = os.read(r, 100).decode().rstrip()
1049-
self.assertEqual("ok: daemon thread are not supported "
1050-
"in subinterpreters", msg)
1041+
_testcapi.run_in_subinterp(%r)
1042+
""" % (subinterp_code,)
1043+
with test.support.SuppressCrashReport():
1044+
rc, out, err = assert_python_failure("-c", script)
1045+
self.assertIn("Fatal Python error: Py_EndInterpreter: "
1046+
"not the last thread", err.decode())
10511047

10521048

10531049
class ThreadingExceptionTests(BaseTestCase):

Lib/threading.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
_allocate_lock = _thread.allocate_lock
3636
_set_sentinel = _thread._set_sentinel
3737
get_ident = _thread.get_ident
38-
_is_main_interpreter = _thread._is_main_interpreter
3938
try:
4039
get_native_id = _thread.get_native_id
4140
_HAVE_THREAD_NATIVE_ID = True
@@ -865,10 +864,6 @@ def start(self):
865864
if self._started.is_set():
866865
raise RuntimeError("threads can only be started once")
867866

868-
if self.daemon and not _is_main_interpreter():
869-
raise RuntimeError("daemon thread are not supported "
870-
"in subinterpreters")
871-
872867
with _active_limbo_lock:
873868
_limbo[self] = self
874869
try:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Allow again to spawn daemon threads in subinterpreters (revert change which
2+
denied them).

Modules/_threadmodule.c

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,6 @@
88
#include "structmember.h" /* offsetof */
99
#include "pythread.h"
1010

11-
#include "clinic/_threadmodule.c.h"
12-
13-
/*[clinic input]
14-
module _thread
15-
[clinic start generated code]*/
16-
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=be8dbe5cc4b16df7]*/
17-
18-
1911
static PyObject *ThreadError;
2012
static PyObject *str_dict;
2113

@@ -1493,21 +1485,6 @@ PyDoc_STRVAR(excepthook_doc,
14931485
\n\
14941486
Handle uncaught Thread.run() exception.");
14951487

1496-
/*[clinic input]
1497-
_thread._is_main_interpreter
1498-
1499-
Return True if the current interpreter is the main Python interpreter.
1500-
[clinic start generated code]*/
1501-
1502-
static PyObject *
1503-
_thread__is_main_interpreter_impl(PyObject *module)
1504-
/*[clinic end generated code: output=7dd82e1728339adc input=cc1eb00fd4598915]*/
1505-
{
1506-
PyThreadState *tstate = _PyThreadState_GET();
1507-
int is_main = _Py_IsMainInterpreter(tstate);
1508-
return PyBool_FromLong(is_main);
1509-
}
1510-
15111488
static PyMethodDef thread_methods[] = {
15121489
{"start_new_thread", (PyCFunction)thread_PyThread_start_new_thread,
15131490
METH_VARARGS, start_new_doc},
@@ -1537,7 +1514,6 @@ static PyMethodDef thread_methods[] = {
15371514
METH_NOARGS, _set_sentinel_doc},
15381515
{"_excepthook", thread_excepthook,
15391516
METH_O, excepthook_doc},
1540-
_THREAD__IS_MAIN_INTERPRETER_METHODDEF
15411517
{NULL, NULL} /* sentinel */
15421518
};
15431519

Modules/clinic/_threadmodule.c.h

Lines changed: 0 additions & 22 deletions
This file was deleted.

0 commit comments

Comments
 (0)