mirror of
https://github.com/python/cpython.git
synced 2025-08-09 03:19:15 +00:00
[3.12] gh-112826: Fix the threading Module When _thread is Missing _is_main_interpreter() (#112850)
Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com> Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
This commit is contained in:
parent
34e9e20cf2
commit
c0fc88fa2f
3 changed files with 51 additions and 1 deletions
|
@ -1895,6 +1895,15 @@ Changes in the Python API
|
||||||
* Mixing tabs and spaces as indentation in the same file is not supported anymore and will
|
* Mixing tabs and spaces as indentation in the same file is not supported anymore and will
|
||||||
raise a :exc:`TabError`.
|
raise a :exc:`TabError`.
|
||||||
|
|
||||||
|
* The :mod:`threading` module now expects the :mod:`!_thread` module to have
|
||||||
|
an ``_is_main_interpreter`` attribute. It is a function with no
|
||||||
|
arguments that returns ``True`` if the current interpreter is the
|
||||||
|
main interpreter.
|
||||||
|
|
||||||
|
Any library or application that provides a custom ``_thread`` module
|
||||||
|
should provide ``_is_main_interpreter()``.
|
||||||
|
(See :gh:`112826`.)
|
||||||
|
|
||||||
Build Changes
|
Build Changes
|
||||||
=============
|
=============
|
||||||
|
|
||||||
|
|
|
@ -1827,6 +1827,34 @@ class MiscTestCase(unittest.TestCase):
|
||||||
support.check__all__(self, threading, ('threading', '_thread'),
|
support.check__all__(self, threading, ('threading', '_thread'),
|
||||||
extra=extra, not_exported=not_exported)
|
extra=extra, not_exported=not_exported)
|
||||||
|
|
||||||
|
@requires_subprocess()
|
||||||
|
def test_gh112826_missing__thread__is_main_interpreter(self):
|
||||||
|
with os_helper.temp_dir() as tempdir:
|
||||||
|
modname = '_thread_fake'
|
||||||
|
import os.path
|
||||||
|
filename = os.path.join(tempdir, modname + '.py')
|
||||||
|
with open(filename, 'w') as outfile:
|
||||||
|
outfile.write("""if True:
|
||||||
|
import _thread
|
||||||
|
globals().update(vars(_thread))
|
||||||
|
del _is_main_interpreter
|
||||||
|
""")
|
||||||
|
|
||||||
|
expected_output = b'success!'
|
||||||
|
_, out, err = assert_python_ok("-c", f"""if True:
|
||||||
|
import sys
|
||||||
|
sys.path.insert(0, {tempdir!r})
|
||||||
|
import {modname}
|
||||||
|
sys.modules['_thread'] = {modname}
|
||||||
|
del sys.modules[{modname!r}]
|
||||||
|
|
||||||
|
import threading
|
||||||
|
print({expected_output.decode('utf-8')!r}, end='')
|
||||||
|
""")
|
||||||
|
|
||||||
|
self.assertEqual(out, expected_output)
|
||||||
|
self.assertEqual(err, b'')
|
||||||
|
|
||||||
|
|
||||||
class InterruptMainTests(unittest.TestCase):
|
class InterruptMainTests(unittest.TestCase):
|
||||||
def check_interrupt_main_with_signal_handler(self, signum):
|
def check_interrupt_main_with_signal_handler(self, signum):
|
||||||
|
|
|
@ -37,7 +37,20 @@ _daemon_threads_allowed = _thread.daemon_threads_allowed
|
||||||
_allocate_lock = _thread.allocate_lock
|
_allocate_lock = _thread.allocate_lock
|
||||||
_set_sentinel = _thread._set_sentinel
|
_set_sentinel = _thread._set_sentinel
|
||||||
get_ident = _thread.get_ident
|
get_ident = _thread.get_ident
|
||||||
_is_main_interpreter = _thread._is_main_interpreter
|
try:
|
||||||
|
_is_main_interpreter = _thread._is_main_interpreter
|
||||||
|
except AttributeError:
|
||||||
|
# See https://github.com/python/cpython/issues/112826.
|
||||||
|
# We can pretend a subinterpreter is the main interpreter for the
|
||||||
|
# sake of _shutdown(), since that only means we do not wait for the
|
||||||
|
# subinterpreter's threads to finish. Instead, they will be stopped
|
||||||
|
# later by the mechanism we use for daemon threads. The likelihood
|
||||||
|
# of this case is small because rarely will the _thread module be
|
||||||
|
# replaced by a module without _is_main_interpreter().
|
||||||
|
# Furthermore, this is all irrelevant in applications
|
||||||
|
# that do not use subinterpreters.
|
||||||
|
def _is_main_interpreter():
|
||||||
|
return True
|
||||||
try:
|
try:
|
||||||
get_native_id = _thread.get_native_id
|
get_native_id = _thread.get_native_id
|
||||||
_HAVE_THREAD_NATIVE_ID = True
|
_HAVE_THREAD_NATIVE_ID = True
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue