summaryrefslogtreecommitdiff
path: root/Lib/test/test_threading.py
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-06-14 18:55:22 +0200
committerGitHub <noreply@github.com>2019-06-14 18:55:22 +0200
commit066e5b1a917ec2134e8997d2cadd815724314252 (patch)
tree963b0b6d7d2ae0c580aa48da0d1423930bf2a32d /Lib/test/test_threading.py
parent212646cae6b7c4ddc8d98c8b9b6d39a5f259e864 (diff)
downloadcpython-git-066e5b1a917ec2134e8997d2cadd815724314252.tar.gz
bpo-37266: Daemon threads are now denied in subinterpreters (GH-14049)
In a subinterpreter, spawning a daemon thread now raises an exception. Daemon threads were never supported in subinterpreters. Previously, the subinterpreter finalization crashed with a Pyton fatal error if a daemon thread was still running. * Add _thread._is_main_interpreter() * threading.Thread.start() now raises RuntimeError if the thread is a daemon thread and the method is called from a subinterpreter. * The _thread module now uses Argument Clinic for the new function. * Use textwrap.dedent() in test_threading.SubinterpThreadingTests
Diffstat (limited to 'Lib/test/test_threading.py')
-rw-r--r--Lib/test/test_threading.py66
1 files changed, 37 insertions, 29 deletions
diff --git a/Lib/test/test_threading.py b/Lib/test/test_threading.py
index 0a0a62bdf9..a04d496001 100644
--- a/Lib/test/test_threading.py
+++ b/Lib/test/test_threading.py
@@ -17,6 +17,7 @@ import weakref
import os
import subprocess
import signal
+import textwrap
from test import lock_tests
from test import support
@@ -928,14 +929,19 @@ class ThreadJoinOnShutdown(BaseTestCase):
class SubinterpThreadingTests(BaseTestCase):
+ def pipe(self):
+ r, w = os.pipe()
+ self.addCleanup(os.close, r)
+ self.addCleanup(os.close, w)
+ if hasattr(os, 'set_blocking'):
+ os.set_blocking(r, False)
+ return (r, w)
def test_threads_join(self):
# Non-daemon threads should be joined at subinterpreter shutdown
# (issue #18808)
- r, w = os.pipe()
- self.addCleanup(os.close, r)
- self.addCleanup(os.close, w)
- code = r"""if 1:
+ r, w = self.pipe()
+ code = textwrap.dedent(r"""
import os
import random
import threading
@@ -953,7 +959,7 @@ class SubinterpThreadingTests(BaseTestCase):
threading.Thread(target=f).start()
random_sleep()
- """ % (w,)
+ """ % (w,))
ret = test.support.run_in_subinterp(code)
self.assertEqual(ret, 0)
# The thread was joined properly.
@@ -964,10 +970,8 @@ class SubinterpThreadingTests(BaseTestCase):
# Python code returned but before the thread state is deleted.
# To achieve this, we register a thread-local object which sleeps
# a bit when deallocated.
- r, w = os.pipe()
- self.addCleanup(os.close, r)
- self.addCleanup(os.close, w)
- code = r"""if 1:
+ r, w = self.pipe()
+ code = textwrap.dedent(r"""
import os
import random
import threading
@@ -992,34 +996,38 @@ class SubinterpThreadingTests(BaseTestCase):
threading.Thread(target=f).start()
random_sleep()
- """ % (w,)
+ """ % (w,))
ret = test.support.run_in_subinterp(code)
self.assertEqual(ret, 0)
# The thread was joined properly.
self.assertEqual(os.read(r, 1), b"x")
- @cpython_only
- def test_daemon_threads_fatal_error(self):
- subinterp_code = r"""if 1:
- import os
+ def test_daemon_thread(self):
+ r, w = self.pipe()
+ code = textwrap.dedent(f"""
import threading
- import time
+ import sys
- def f():
- # Make sure the daemon thread is still running when
- # Py_EndInterpreter is called.
- time.sleep(10)
- threading.Thread(target=f, daemon=True).start()
- """
- script = r"""if 1:
- import _testcapi
+ channel = open({w}, "w", closefd=False)
+
+ def func():
+ pass
+
+ thread = threading.Thread(target=func, daemon=True)
+ try:
+ thread.start()
+ except RuntimeError as exc:
+ print("ok: %s" % exc, file=channel, flush=True)
+ else:
+ thread.join()
+ print("fail: RuntimeError not raised", file=channel, flush=True)
+ """)
+ ret = test.support.run_in_subinterp(code)
+ self.assertEqual(ret, 0)
- _testcapi.run_in_subinterp(%r)
- """ % (subinterp_code,)
- with test.support.SuppressCrashReport():
- rc, out, err = assert_python_failure("-c", script)
- self.assertIn("Fatal Python error: Py_EndInterpreter: "
- "not the last thread", err.decode())
+ msg = os.read(r, 100).decode().rstrip()
+ self.assertEqual("ok: daemon thread are not supported "
+ "in subinterpreters", msg)
class ThreadingExceptionTests(BaseTestCase):