gh-104690 Disallow thread creation and fork at interpreter finalization (#104826)

Disallow thread creation and fork at interpreter finalization.

in the following functions, check if interpreter is finalizing and raise `RuntimeError` with appropriate message:
* `_thread.start_new_thread` and thus `threading`
* `posix.fork`
* `posix.fork1`
* `posix.forkpty`
* `_posixsubprocess.fork_exec` when a `preexec_fn=` is supplied.

---------

Co-authored-by: blurb-it[bot] <43283697+blurb-it[bot]@users.noreply.github.com>
Co-authored-by: Gregory P. Smith <greg@krypto.org>
This commit is contained in:
chgnrdv 2023-06-04 07:06:45 +03:00 committed by GitHub
parent eaff9c39aa
commit ce558e69d4
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 97 additions and 30 deletions

View file

@ -531,34 +531,6 @@ class ThreadTests(BaseTestCase):
t = threading.Thread(daemon=True)
self.assertTrue(t.daemon)
@support.requires_fork()
def test_fork_at_exit(self):
# bpo-42350: Calling os.fork() after threading._shutdown() must
# not log an error.
code = textwrap.dedent("""
import atexit
import os
import sys
from test.support import wait_process
# Import the threading module to register its "at fork" callback
import threading
def exit_handler():
pid = os.fork()
if not pid:
print("child process ok", file=sys.stderr, flush=True)
# child process
else:
wait_process(pid, exitcode=0)
# exit_handler() will be called after threading._shutdown()
atexit.register(exit_handler)
""")
_, out, err = assert_python_ok("-c", code)
self.assertEqual(out, b'')
self.assertEqual(err.rstrip(), b'child process ok')
@support.requires_fork()
def test_dummy_thread_after_fork(self):
# Issue #14308: a dummy thread in the active list doesn't mess up
@ -1048,6 +1020,22 @@ class ThreadTests(BaseTestCase):
self.assertEqual(out, b'')
self.assertEqual(err, b'')
def test_start_new_thread_at_exit(self):
code = """if 1:
import atexit
import _thread
def f():
print("shouldn't be printed")
def exit_handler():
_thread.start_new_thread(f, ())
atexit.register(exit_handler)
"""
_, out, err = assert_python_ok("-c", code)
self.assertEqual(out, b'')
self.assertIn(b"can't create new thread at interpreter shutdown", err)
class ThreadJoinOnShutdown(BaseTestCase):