mirror of
https://github.com/python/cpython.git
synced 2025-11-01 22:21:35 +00:00
gh-135427: Fix DeprecationWarning for os.fork when run in threads with -Werror (GH-136796)
Don't ignore errors raised by `PyErr_WarnFormat` in `warn_about_fork_with_threads` Instead, ignore the warnings in all test code that forks. (That's a lot of functions.) In `test_support`, make `ignore_warnings` a context manager (as well as decorator), and add a `message` argument to it. Also add a `ignore_fork_in_thread_deprecation_warnings` helper for the deadlock-in-fork warning.
This commit is contained in:
parent
f60f8225ed
commit
fd8f42d3d1
27 changed files with 390 additions and 69 deletions
File diff suppressed because it is too large
Load diff
|
|
@ -1,11 +1,11 @@
|
||||||
import contextlib
|
import contextlib
|
||||||
import functools
|
|
||||||
import importlib
|
import importlib
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def import_deprecated(name):
|
def import_deprecated(name):
|
||||||
"""Import *name* while suppressing DeprecationWarning."""
|
"""Import *name* while suppressing DeprecationWarning."""
|
||||||
with warnings.catch_warnings():
|
with warnings.catch_warnings():
|
||||||
|
|
@ -42,20 +42,32 @@ def check_syntax_warning(testcase, statement, errtext='',
|
||||||
testcase.assertEqual(warns, [])
|
testcase.assertEqual(warns, [])
|
||||||
|
|
||||||
|
|
||||||
def ignore_warnings(*, category):
|
@contextlib.contextmanager
|
||||||
|
def ignore_warnings(*, category, message=''):
|
||||||
"""Decorator to suppress warnings.
|
"""Decorator to suppress warnings.
|
||||||
|
|
||||||
Use of context managers to hide warnings make diffs
|
Can also be used as a context manager. This is not preferred,
|
||||||
more noisy and tools like 'git blame' less useful.
|
because it makes diffs more noisy and tools like 'git blame' less useful.
|
||||||
|
But, it's useful for async functions.
|
||||||
"""
|
"""
|
||||||
def decorator(test):
|
with warnings.catch_warnings():
|
||||||
@functools.wraps(test)
|
warnings.filterwarnings('ignore', category=category, message=message)
|
||||||
def wrapper(self, *args, **kwargs):
|
yield
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter('ignore', category=category)
|
|
||||||
return test(self, *args, **kwargs)
|
@contextlib.contextmanager
|
||||||
return wrapper
|
def ignore_fork_in_thread_deprecation_warnings():
|
||||||
return decorator
|
"""Suppress deprecation warnings related to forking in multi-threaded code.
|
||||||
|
|
||||||
|
See gh-135427
|
||||||
|
|
||||||
|
Can be used as decorator (preferred) or context manager.
|
||||||
|
"""
|
||||||
|
with ignore_warnings(
|
||||||
|
message=".*fork.*may lead to deadlocks in the child.*",
|
||||||
|
category=DeprecationWarning,
|
||||||
|
):
|
||||||
|
yield
|
||||||
|
|
||||||
|
|
||||||
class WarningsRecorder(object):
|
class WarningsRecorder(object):
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,7 @@
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import os_helper
|
from test.support import os_helper, warnings_helper
|
||||||
from test.support import socket_helper
|
from test.support import socket_helper
|
||||||
from test.support import wait_process
|
from test.support import wait_process
|
||||||
from test.support import hashlib_helper
|
from test.support import hashlib_helper
|
||||||
|
|
@ -1183,29 +1183,31 @@ async def runner():
|
||||||
class TestFork(unittest.IsolatedAsyncioTestCase):
|
class TestFork(unittest.IsolatedAsyncioTestCase):
|
||||||
|
|
||||||
async def test_fork_not_share_event_loop(self):
|
async def test_fork_not_share_event_loop(self):
|
||||||
# The forked process should not share the event loop with the parent
|
with warnings_helper.ignore_fork_in_thread_deprecation_warnings():
|
||||||
loop = asyncio.get_running_loop()
|
# The forked process should not share the event loop with the parent
|
||||||
r, w = os.pipe()
|
loop = asyncio.get_running_loop()
|
||||||
self.addCleanup(os.close, r)
|
r, w = os.pipe()
|
||||||
self.addCleanup(os.close, w)
|
self.addCleanup(os.close, r)
|
||||||
pid = os.fork()
|
self.addCleanup(os.close, w)
|
||||||
if pid == 0:
|
pid = os.fork()
|
||||||
# child
|
if pid == 0:
|
||||||
try:
|
# child
|
||||||
loop = asyncio.get_event_loop()
|
try:
|
||||||
os.write(w, b'LOOP:' + str(id(loop)).encode())
|
loop = asyncio.get_event_loop()
|
||||||
except RuntimeError:
|
os.write(w, b'LOOP:' + str(id(loop)).encode())
|
||||||
os.write(w, b'NO LOOP')
|
except RuntimeError:
|
||||||
except BaseException as e:
|
os.write(w, b'NO LOOP')
|
||||||
os.write(w, b'ERROR:' + ascii(e).encode())
|
except BaseException as e:
|
||||||
finally:
|
os.write(w, b'ERROR:' + ascii(e).encode())
|
||||||
os._exit(0)
|
finally:
|
||||||
else:
|
os._exit(0)
|
||||||
# parent
|
else:
|
||||||
result = os.read(r, 100)
|
# parent
|
||||||
self.assertEqual(result, b'NO LOOP')
|
result = os.read(r, 100)
|
||||||
wait_process(pid, exitcode=0)
|
self.assertEqual(result, b'NO LOOP')
|
||||||
|
wait_process(pid, exitcode=0)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@hashlib_helper.requires_hashdigest('md5')
|
@hashlib_helper.requires_hashdigest('md5')
|
||||||
@support.skip_if_sanitizer("TSAN doesn't support threads after fork", thread=True)
|
@support.skip_if_sanitizer("TSAN doesn't support threads after fork", thread=True)
|
||||||
def test_fork_signal_handling(self):
|
def test_fork_signal_handling(self):
|
||||||
|
|
@ -1253,6 +1255,7 @@ async def func():
|
||||||
self.assertFalse(parent_handled.is_set())
|
self.assertFalse(parent_handled.is_set())
|
||||||
self.assertTrue(child_handled.is_set())
|
self.assertTrue(child_handled.is_set())
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@hashlib_helper.requires_hashdigest('md5')
|
@hashlib_helper.requires_hashdigest('md5')
|
||||||
@support.skip_if_sanitizer("TSAN doesn't support threads after fork", thread=True)
|
@support.skip_if_sanitizer("TSAN doesn't support threads after fork", thread=True)
|
||||||
def test_fork_asyncio_run(self):
|
def test_fork_asyncio_run(self):
|
||||||
|
|
@ -1273,6 +1276,7 @@ async def child_main():
|
||||||
|
|
||||||
self.assertEqual(result.value, 42)
|
self.assertEqual(result.value, 42)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@hashlib_helper.requires_hashdigest('md5')
|
@hashlib_helper.requires_hashdigest('md5')
|
||||||
@support.skip_if_sanitizer("TSAN doesn't support threads after fork", thread=True)
|
@support.skip_if_sanitizer("TSAN doesn't support threads after fork", thread=True)
|
||||||
def test_fork_asyncio_subprocess(self):
|
def test_fork_asyncio_subprocess(self):
|
||||||
|
|
|
||||||
|
|
@ -31,6 +31,7 @@
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import cpython_only, swap_attr
|
from test.support import cpython_only, swap_attr
|
||||||
from test.support import async_yield, run_yielding_async_fn
|
from test.support import async_yield, run_yielding_async_fn
|
||||||
|
from test.support import warnings_helper
|
||||||
from test.support.import_helper import import_module
|
from test.support.import_helper import import_module
|
||||||
from test.support.os_helper import (EnvironmentVarGuard, TESTFN, unlink)
|
from test.support.os_helper import (EnvironmentVarGuard, TESTFN, unlink)
|
||||||
from test.support.script_helper import assert_python_ok
|
from test.support.script_helper import assert_python_ok
|
||||||
|
|
@ -2545,6 +2546,7 @@ def run_child(self, child, terminal_input):
|
||||||
finally:
|
finally:
|
||||||
signal.signal(signal.SIGHUP, old_sighup)
|
signal.signal(signal.SIGHUP, old_sighup)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def _run_child(self, child, terminal_input):
|
def _run_child(self, child, terminal_input):
|
||||||
r, w = os.pipe() # Pipe test results from child back to parent
|
r, w = os.pipe() # Pipe test results from child back to parent
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
from operator import add
|
from operator import add
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import Py_GIL_DISABLED
|
from test.support import Py_GIL_DISABLED, warnings_helper
|
||||||
|
|
||||||
|
|
||||||
def mul(x, y):
|
def mul(x, y):
|
||||||
|
|
@ -43,10 +43,12 @@ class ExecutorTest:
|
||||||
|
|
||||||
# Executor.shutdown() and context manager usage is tested by
|
# Executor.shutdown() and context manager usage is tested by
|
||||||
# ExecutorShutdownTest.
|
# ExecutorShutdownTest.
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_submit(self):
|
def test_submit(self):
|
||||||
future = self.executor.submit(pow, 2, 8)
|
future = self.executor.submit(pow, 2, 8)
|
||||||
self.assertEqual(256, future.result())
|
self.assertEqual(256, future.result())
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_submit_keyword(self):
|
def test_submit_keyword(self):
|
||||||
future = self.executor.submit(mul, 2, y=8)
|
future = self.executor.submit(mul, 2, y=8)
|
||||||
self.assertEqual(16, future.result())
|
self.assertEqual(16, future.result())
|
||||||
|
|
@ -57,6 +59,7 @@ def test_submit_keyword(self):
|
||||||
with self.assertRaises(TypeError):
|
with self.assertRaises(TypeError):
|
||||||
self.executor.submit(arg=1)
|
self.executor.submit(arg=1)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_map(self):
|
def test_map(self):
|
||||||
self.assertEqual(
|
self.assertEqual(
|
||||||
list(self.executor.map(pow, range(10), range(10))),
|
list(self.executor.map(pow, range(10), range(10))),
|
||||||
|
|
@ -66,6 +69,7 @@ def test_map(self):
|
||||||
list(self.executor.map(pow, range(10), range(10), chunksize=3)),
|
list(self.executor.map(pow, range(10), range(10), chunksize=3)),
|
||||||
list(map(pow, range(10), range(10))))
|
list(map(pow, range(10), range(10))))
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_map_exception(self):
|
def test_map_exception(self):
|
||||||
i = self.executor.map(divmod, [1, 1, 1, 1], [2, 3, 0, 5])
|
i = self.executor.map(divmod, [1, 1, 1, 1], [2, 3, 0, 5])
|
||||||
self.assertEqual(i.__next__(), (0, 1))
|
self.assertEqual(i.__next__(), (0, 1))
|
||||||
|
|
@ -73,6 +77,7 @@ def test_map_exception(self):
|
||||||
with self.assertRaises(ZeroDivisionError):
|
with self.assertRaises(ZeroDivisionError):
|
||||||
i.__next__()
|
i.__next__()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@support.requires_resource('walltime')
|
@support.requires_resource('walltime')
|
||||||
def test_map_timeout(self):
|
def test_map_timeout(self):
|
||||||
results = []
|
results = []
|
||||||
|
|
@ -108,6 +113,7 @@ def test_map_buffersize_value_validation(self):
|
||||||
):
|
):
|
||||||
self.executor.map(str, range(4), buffersize=buffersize)
|
self.executor.map(str, range(4), buffersize=buffersize)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_map_buffersize(self):
|
def test_map_buffersize(self):
|
||||||
ints = range(4)
|
ints = range(4)
|
||||||
for buffersize in (1, 2, len(ints), len(ints) * 2):
|
for buffersize in (1, 2, len(ints), len(ints) * 2):
|
||||||
|
|
@ -115,6 +121,7 @@ def test_map_buffersize(self):
|
||||||
res = self.executor.map(str, ints, buffersize=buffersize)
|
res = self.executor.map(str, ints, buffersize=buffersize)
|
||||||
self.assertListEqual(list(res), ["0", "1", "2", "3"])
|
self.assertListEqual(list(res), ["0", "1", "2", "3"])
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_map_buffersize_on_multiple_iterables(self):
|
def test_map_buffersize_on_multiple_iterables(self):
|
||||||
ints = range(4)
|
ints = range(4)
|
||||||
for buffersize in (1, 2, len(ints), len(ints) * 2):
|
for buffersize in (1, 2, len(ints), len(ints) * 2):
|
||||||
|
|
@ -122,12 +129,14 @@ def test_map_buffersize_on_multiple_iterables(self):
|
||||||
res = self.executor.map(add, ints, ints, buffersize=buffersize)
|
res = self.executor.map(add, ints, ints, buffersize=buffersize)
|
||||||
self.assertListEqual(list(res), [0, 2, 4, 6])
|
self.assertListEqual(list(res), [0, 2, 4, 6])
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_map_buffersize_on_infinite_iterable(self):
|
def test_map_buffersize_on_infinite_iterable(self):
|
||||||
res = self.executor.map(str, itertools.count(), buffersize=2)
|
res = self.executor.map(str, itertools.count(), buffersize=2)
|
||||||
self.assertEqual(next(res, None), "0")
|
self.assertEqual(next(res, None), "0")
|
||||||
self.assertEqual(next(res, None), "1")
|
self.assertEqual(next(res, None), "1")
|
||||||
self.assertEqual(next(res, None), "2")
|
self.assertEqual(next(res, None), "2")
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_map_buffersize_on_multiple_infinite_iterables(self):
|
def test_map_buffersize_on_multiple_infinite_iterables(self):
|
||||||
res = self.executor.map(
|
res = self.executor.map(
|
||||||
add,
|
add,
|
||||||
|
|
@ -147,6 +156,7 @@ def test_map_buffersize_without_iterable(self):
|
||||||
res = self.executor.map(str, buffersize=2)
|
res = self.executor.map(str, buffersize=2)
|
||||||
self.assertIsNone(next(res, None))
|
self.assertIsNone(next(res, None))
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_map_buffersize_when_buffer_is_full(self):
|
def test_map_buffersize_when_buffer_is_full(self):
|
||||||
ints = iter(range(4))
|
ints = iter(range(4))
|
||||||
buffersize = 2
|
buffersize = 2
|
||||||
|
|
@ -158,6 +168,7 @@ def test_map_buffersize_when_buffer_is_full(self):
|
||||||
msg="should have fetched only `buffersize` elements from `ints`.",
|
msg="should have fetched only `buffersize` elements from `ints`.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_shutdown_race_issue12456(self):
|
def test_shutdown_race_issue12456(self):
|
||||||
# Issue #12456: race condition at shutdown where trying to post a
|
# Issue #12456: race condition at shutdown where trying to post a
|
||||||
# sentinel in the call queue blocks (the queue is full while processes
|
# sentinel in the call queue blocks (the queue is full while processes
|
||||||
|
|
@ -165,6 +176,7 @@ def test_shutdown_race_issue12456(self):
|
||||||
self.executor.map(str, [2] * (self.worker_count + 1))
|
self.executor.map(str, [2] * (self.worker_count + 1))
|
||||||
self.executor.shutdown()
|
self.executor.shutdown()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@support.cpython_only
|
@support.cpython_only
|
||||||
def test_no_stale_references(self):
|
def test_no_stale_references(self):
|
||||||
# Issue #16284: check that the executors don't unnecessarily hang onto
|
# Issue #16284: check that the executors don't unnecessarily hang onto
|
||||||
|
|
@ -209,6 +221,7 @@ def test_max_workers_negative(self):
|
||||||
"than 0"):
|
"than 0"):
|
||||||
self.executor_type(max_workers=number)
|
self.executor_type(max_workers=number)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_free_reference(self):
|
def test_free_reference(self):
|
||||||
# Issue #14406: Result iterator should not keep an internal
|
# Issue #14406: Result iterator should not keep an internal
|
||||||
# reference to result objects.
|
# reference to result objects.
|
||||||
|
|
@ -221,6 +234,7 @@ def test_free_reference(self):
|
||||||
if wr() is None:
|
if wr() is None:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_swallows_falsey_exceptions(self):
|
def test_swallows_falsey_exceptions(self):
|
||||||
# see gh-132063: Prevent exceptions that evaluate as falsey
|
# see gh-132063: Prevent exceptions that evaluate as falsey
|
||||||
# from being ignored.
|
# from being ignored.
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
CANCELLED_AND_NOTIFIED, FINISHED, Future)
|
CANCELLED_AND_NOTIFIED, FINISHED, Future)
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
|
from test.support import warnings_helper
|
||||||
|
|
||||||
from .util import (
|
from .util import (
|
||||||
PENDING_FUTURE, RUNNING_FUTURE,
|
PENDING_FUTURE, RUNNING_FUTURE,
|
||||||
|
|
@ -19,6 +20,7 @@ def mul(x, y):
|
||||||
|
|
||||||
|
|
||||||
class AsCompletedTests:
|
class AsCompletedTests:
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_no_timeout(self):
|
def test_no_timeout(self):
|
||||||
future1 = self.executor.submit(mul, 2, 21)
|
future1 = self.executor.submit(mul, 2, 21)
|
||||||
future2 = self.executor.submit(mul, 7, 6)
|
future2 = self.executor.submit(mul, 7, 6)
|
||||||
|
|
@ -35,6 +37,7 @@ def test_no_timeout(self):
|
||||||
future1, future2]),
|
future1, future2]),
|
||||||
completed)
|
completed)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_future_times_out(self):
|
def test_future_times_out(self):
|
||||||
"""Test ``futures.as_completed`` timing out before
|
"""Test ``futures.as_completed`` timing out before
|
||||||
completing it's final future."""
|
completing it's final future."""
|
||||||
|
|
@ -62,6 +65,7 @@ def test_future_times_out(self):
|
||||||
# Check that ``future`` wasn't completed.
|
# Check that ``future`` wasn't completed.
|
||||||
self.assertEqual(completed_futures, already_completed)
|
self.assertEqual(completed_futures, already_completed)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_duplicate_futures(self):
|
def test_duplicate_futures(self):
|
||||||
# Issue 20367. Duplicate futures should not raise exceptions or give
|
# Issue 20367. Duplicate futures should not raise exceptions or give
|
||||||
# duplicate responses.
|
# duplicate responses.
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@
|
||||||
from concurrent.futures.process import BrokenProcessPool, _ThreadWakeup
|
from concurrent.futures.process import BrokenProcessPool, _ThreadWakeup
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
|
from test.support import warnings_helper
|
||||||
|
|
||||||
from .util import (
|
from .util import (
|
||||||
create_executor_tests, setup_module,
|
create_executor_tests, setup_module,
|
||||||
|
|
@ -111,6 +112,7 @@ def _fail_on_deadlock(self, executor):
|
||||||
print(f"\nTraceback:\n {tb}", file=sys.__stderr__)
|
print(f"\nTraceback:\n {tb}", file=sys.__stderr__)
|
||||||
self.fail(f"Executor deadlock:\n\n{tb}")
|
self.fail(f"Executor deadlock:\n\n{tb}")
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def _check_error(self, error, func, *args, ignore_stderr=False):
|
def _check_error(self, error, func, *args, ignore_stderr=False):
|
||||||
# test for deadlock caused by crashes or exiting in a pool
|
# test for deadlock caused by crashes or exiting in a pool
|
||||||
self.executor.shutdown(wait=True)
|
self.executor.shutdown(wait=True)
|
||||||
|
|
@ -199,6 +201,7 @@ def test_exit_during_result_unpickle_in_result_handler(self):
|
||||||
# the result_handler thread
|
# the result_handler thread
|
||||||
self._check_error(BrokenProcessPool, _return_instance, ExitAtUnpickle)
|
self._check_error(BrokenProcessPool, _return_instance, ExitAtUnpickle)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@support.skip_if_sanitizer("UBSan: explicit SIGSEV not allowed", ub=True)
|
@support.skip_if_sanitizer("UBSan: explicit SIGSEV not allowed", ub=True)
|
||||||
def test_shutdown_deadlock(self):
|
def test_shutdown_deadlock(self):
|
||||||
# Test that the pool calling shutdown do not cause deadlock
|
# Test that the pool calling shutdown do not cause deadlock
|
||||||
|
|
@ -212,6 +215,7 @@ def test_shutdown_deadlock(self):
|
||||||
with self.assertRaises(BrokenProcessPool):
|
with self.assertRaises(BrokenProcessPool):
|
||||||
f.result()
|
f.result()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_shutdown_deadlock_pickle(self):
|
def test_shutdown_deadlock_pickle(self):
|
||||||
# Test that the pool calling shutdown with wait=False does not cause
|
# Test that the pool calling shutdown with wait=False does not cause
|
||||||
# a deadlock if a task fails at pickle after the shutdown call.
|
# a deadlock if a task fails at pickle after the shutdown call.
|
||||||
|
|
@ -238,6 +242,7 @@ def test_shutdown_deadlock_pickle(self):
|
||||||
# dangling threads
|
# dangling threads
|
||||||
executor_manager.join()
|
executor_manager.join()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@support.skip_if_sanitizer("UBSan: explicit SIGSEV not allowed", ub=True)
|
@support.skip_if_sanitizer("UBSan: explicit SIGSEV not allowed", ub=True)
|
||||||
def test_crash_big_data(self):
|
def test_crash_big_data(self):
|
||||||
# Test that there is a clean exception instead of a deadlock when a
|
# Test that there is a clean exception instead of a deadlock when a
|
||||||
|
|
@ -254,6 +259,7 @@ def test_crash_big_data(self):
|
||||||
|
|
||||||
executor.shutdown(wait=True)
|
executor.shutdown(wait=True)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_gh105829_should_not_deadlock_if_wakeup_pipe_full(self):
|
def test_gh105829_should_not_deadlock_if_wakeup_pipe_full(self):
|
||||||
# Issue #105829: The _ExecutorManagerThread wakeup pipe could
|
# Issue #105829: The _ExecutorManagerThread wakeup pipe could
|
||||||
# fill up and block. See: https://github.com/python/cpython/issues/105829
|
# fill up and block. See: https://github.com/python/cpython/issues/105829
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
from logging.handlers import QueueHandler
|
from logging.handlers import QueueHandler
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
|
from test.support import warnings_helper
|
||||||
|
|
||||||
from .util import ExecutorMixin, create_executor_tests, setup_module
|
from .util import ExecutorMixin, create_executor_tests, setup_module
|
||||||
|
|
||||||
|
|
@ -48,6 +49,7 @@ def setUp(self):
|
||||||
initargs=('initialized',))
|
initargs=('initialized',))
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_initializer(self):
|
def test_initializer(self):
|
||||||
futures = [self.executor.submit(get_init_status)
|
futures = [self.executor.submit(get_init_status)
|
||||||
for _ in range(self.worker_count)]
|
for _ in range(self.worker_count)]
|
||||||
|
|
@ -74,6 +76,7 @@ def setUp(self):
|
||||||
self.executor_kwargs = dict(initializer=init_fail)
|
self.executor_kwargs = dict(initializer=init_fail)
|
||||||
super().setUp()
|
super().setUp()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_initializer(self):
|
def test_initializer(self):
|
||||||
with self._assert_logged('ValueError: error in initializer'):
|
with self._assert_logged('ValueError: error in initializer'):
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -9,7 +9,7 @@
|
||||||
from concurrent.futures.process import BrokenProcessPool
|
from concurrent.futures.process import BrokenProcessPool
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import hashlib_helper
|
from test.support import hashlib_helper, warnings_helper
|
||||||
from test.test_importlib.metadata.fixtures import parameterize
|
from test.test_importlib.metadata.fixtures import parameterize
|
||||||
|
|
||||||
from .executor import ExecutorTest, mul
|
from .executor import ExecutorTest, mul
|
||||||
|
|
@ -49,6 +49,7 @@ def test_max_workers_too_large(self):
|
||||||
"max_workers must be <= 61"):
|
"max_workers must be <= 61"):
|
||||||
futures.ProcessPoolExecutor(max_workers=62)
|
futures.ProcessPoolExecutor(max_workers=62)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_killed_child(self):
|
def test_killed_child(self):
|
||||||
# When a child process is abruptly terminated, the whole pool gets
|
# When a child process is abruptly terminated, the whole pool gets
|
||||||
# "broken".
|
# "broken".
|
||||||
|
|
@ -61,6 +62,7 @@ def test_killed_child(self):
|
||||||
# Submitting other jobs fails as well.
|
# Submitting other jobs fails as well.
|
||||||
self.assertRaises(BrokenProcessPool, self.executor.submit, pow, 2, 8)
|
self.assertRaises(BrokenProcessPool, self.executor.submit, pow, 2, 8)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_map_chunksize(self):
|
def test_map_chunksize(self):
|
||||||
def bad_map():
|
def bad_map():
|
||||||
list(self.executor.map(pow, range(40), range(40), chunksize=-1))
|
list(self.executor.map(pow, range(40), range(40), chunksize=-1))
|
||||||
|
|
@ -81,6 +83,7 @@ def bad_map():
|
||||||
def _test_traceback(cls):
|
def _test_traceback(cls):
|
||||||
raise RuntimeError(123) # some comment
|
raise RuntimeError(123) # some comment
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_traceback(self):
|
def test_traceback(self):
|
||||||
# We want ensure that the traceback from the child process is
|
# We want ensure that the traceback from the child process is
|
||||||
# contained in the traceback raised in the main process.
|
# contained in the traceback raised in the main process.
|
||||||
|
|
@ -103,6 +106,7 @@ def test_traceback(self):
|
||||||
self.assertIn('raise RuntimeError(123) # some comment',
|
self.assertIn('raise RuntimeError(123) # some comment',
|
||||||
f1.getvalue())
|
f1.getvalue())
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@hashlib_helper.requires_hashdigest('md5')
|
@hashlib_helper.requires_hashdigest('md5')
|
||||||
def test_ressources_gced_in_workers(self):
|
def test_ressources_gced_in_workers(self):
|
||||||
# Ensure that argument for a job are correctly gc-ed after the job
|
# Ensure that argument for a job are correctly gc-ed after the job
|
||||||
|
|
@ -123,6 +127,7 @@ def test_ressources_gced_in_workers(self):
|
||||||
mgr.shutdown()
|
mgr.shutdown()
|
||||||
mgr.join()
|
mgr.join()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_saturation(self):
|
def test_saturation(self):
|
||||||
executor = self.executor
|
executor = self.executor
|
||||||
mp_context = self.get_context()
|
mp_context = self.get_context()
|
||||||
|
|
@ -208,6 +213,7 @@ def test_max_tasks_early_shutdown(self):
|
||||||
for i, future in enumerate(futures):
|
for i, future in enumerate(futures):
|
||||||
self.assertEqual(future.result(), mul(i, i))
|
self.assertEqual(future.result(), mul(i, i))
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_python_finalization_error(self):
|
def test_python_finalization_error(self):
|
||||||
# gh-109047: Catch RuntimeError on thread creation
|
# gh-109047: Catch RuntimeError on thread creation
|
||||||
# during Python finalization.
|
# during Python finalization.
|
||||||
|
|
@ -258,6 +264,7 @@ def test_force_shutdown_workers_invalid_op(self):
|
||||||
executor._force_shutdown,
|
executor._force_shutdown,
|
||||||
operation='invalid operation'),
|
operation='invalid operation'),
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@parameterize(*FORCE_SHUTDOWN_PARAMS)
|
@parameterize(*FORCE_SHUTDOWN_PARAMS)
|
||||||
def test_force_shutdown_workers(self, function_name):
|
def test_force_shutdown_workers(self, function_name):
|
||||||
manager = self.get_context().Manager()
|
manager = self.get_context().Manager()
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
|
from test.support import warnings_helper
|
||||||
from test.support.script_helper import assert_python_ok
|
from test.support.script_helper import assert_python_ok
|
||||||
|
|
||||||
from .util import (
|
from .util import (
|
||||||
|
|
@ -78,12 +79,14 @@ def run_last():
|
||||||
self.assertIn("RuntimeError: cannot schedule new futures", err.decode())
|
self.assertIn("RuntimeError: cannot schedule new futures", err.decode())
|
||||||
self.assertEqual(out.strip(), b"runtime-error")
|
self.assertEqual(out.strip(), b"runtime-error")
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_hang_issue12364(self):
|
def test_hang_issue12364(self):
|
||||||
fs = [self.executor.submit(time.sleep, 0.1) for _ in range(50)]
|
fs = [self.executor.submit(time.sleep, 0.1) for _ in range(50)]
|
||||||
self.executor.shutdown()
|
self.executor.shutdown()
|
||||||
for f in fs:
|
for f in fs:
|
||||||
f.result()
|
f.result()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_cancel_futures(self):
|
def test_cancel_futures(self):
|
||||||
assert self.worker_count <= 5, "test needs few workers"
|
assert self.worker_count <= 5, "test needs few workers"
|
||||||
fs = [self.executor.submit(time.sleep, .1) for _ in range(50)]
|
fs = [self.executor.submit(time.sleep, .1) for _ in range(50)]
|
||||||
|
|
@ -129,6 +132,7 @@ def test_hang_gh83386(self):
|
||||||
self.assertFalse(err)
|
self.assertFalse(err)
|
||||||
self.assertEqual(out.strip(), b"apple")
|
self.assertEqual(out.strip(), b"apple")
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_hang_gh94440(self):
|
def test_hang_gh94440(self):
|
||||||
"""shutdown(wait=True) doesn't hang when a future was submitted and
|
"""shutdown(wait=True) doesn't hang when a future was submitted and
|
||||||
quickly canceled right before shutdown.
|
quickly canceled right before shutdown.
|
||||||
|
|
@ -172,6 +176,7 @@ def acquire_lock(lock):
|
||||||
for t in self.executor._threads:
|
for t in self.executor._threads:
|
||||||
t.join()
|
t.join()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_context_manager_shutdown(self):
|
def test_context_manager_shutdown(self):
|
||||||
with futures.ThreadPoolExecutor(max_workers=5) as e:
|
with futures.ThreadPoolExecutor(max_workers=5) as e:
|
||||||
executor = e
|
executor = e
|
||||||
|
|
@ -181,6 +186,7 @@ def test_context_manager_shutdown(self):
|
||||||
for t in executor._threads:
|
for t in executor._threads:
|
||||||
t.join()
|
t.join()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_del_shutdown(self):
|
def test_del_shutdown(self):
|
||||||
executor = futures.ThreadPoolExecutor(max_workers=5)
|
executor = futures.ThreadPoolExecutor(max_workers=5)
|
||||||
res = executor.map(abs, range(-5, 5))
|
res = executor.map(abs, range(-5, 5))
|
||||||
|
|
@ -194,6 +200,7 @@ def test_del_shutdown(self):
|
||||||
# executor got shutdown.
|
# executor got shutdown.
|
||||||
assert all([r == abs(v) for r, v in zip(res, range(-5, 5))])
|
assert all([r == abs(v) for r, v in zip(res, range(-5, 5))])
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_shutdown_no_wait(self):
|
def test_shutdown_no_wait(self):
|
||||||
# Ensure that the executor cleans up the threads when calling
|
# Ensure that the executor cleans up the threads when calling
|
||||||
# shutdown with wait=False
|
# shutdown with wait=False
|
||||||
|
|
@ -208,7 +215,7 @@ def test_shutdown_no_wait(self):
|
||||||
# executor got shutdown.
|
# executor got shutdown.
|
||||||
assert all([r == abs(v) for r, v in zip(res, range(-5, 5))])
|
assert all([r == abs(v) for r, v in zip(res, range(-5, 5))])
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_thread_names_assigned(self):
|
def test_thread_names_assigned(self):
|
||||||
executor = futures.ThreadPoolExecutor(
|
executor = futures.ThreadPoolExecutor(
|
||||||
max_workers=5, thread_name_prefix='SpecialPool')
|
max_workers=5, thread_name_prefix='SpecialPool')
|
||||||
|
|
@ -221,6 +228,7 @@ def test_thread_names_assigned(self):
|
||||||
self.assertRegex(t.name, r'^SpecialPool_[0-4]$')
|
self.assertRegex(t.name, r'^SpecialPool_[0-4]$')
|
||||||
t.join()
|
t.join()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_thread_names_default(self):
|
def test_thread_names_default(self):
|
||||||
executor = futures.ThreadPoolExecutor(max_workers=5)
|
executor = futures.ThreadPoolExecutor(max_workers=5)
|
||||||
executor.map(abs, range(-5, 5))
|
executor.map(abs, range(-5, 5))
|
||||||
|
|
@ -254,6 +262,7 @@ def test_cancel_futures_wait_false(self):
|
||||||
|
|
||||||
|
|
||||||
class ProcessPoolShutdownTest(ExecutorShutdownTest):
|
class ProcessPoolShutdownTest(ExecutorShutdownTest):
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_processes_terminate(self):
|
def test_processes_terminate(self):
|
||||||
def acquire_lock(lock):
|
def acquire_lock(lock):
|
||||||
lock.acquire()
|
lock.acquire()
|
||||||
|
|
@ -277,6 +286,7 @@ def acquire_lock(lock):
|
||||||
for p in processes.values():
|
for p in processes.values():
|
||||||
p.join()
|
p.join()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_context_manager_shutdown(self):
|
def test_context_manager_shutdown(self):
|
||||||
with futures.ProcessPoolExecutor(
|
with futures.ProcessPoolExecutor(
|
||||||
max_workers=5, mp_context=self.get_context()) as e:
|
max_workers=5, mp_context=self.get_context()) as e:
|
||||||
|
|
@ -287,6 +297,7 @@ def test_context_manager_shutdown(self):
|
||||||
for p in processes.values():
|
for p in processes.values():
|
||||||
p.join()
|
p.join()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_del_shutdown(self):
|
def test_del_shutdown(self):
|
||||||
executor = futures.ProcessPoolExecutor(
|
executor = futures.ProcessPoolExecutor(
|
||||||
max_workers=5, mp_context=self.get_context())
|
max_workers=5, mp_context=self.get_context())
|
||||||
|
|
@ -309,6 +320,7 @@ def test_del_shutdown(self):
|
||||||
# executor got shutdown.
|
# executor got shutdown.
|
||||||
assert all([r == abs(v) for r, v in zip(res, range(-5, 5))])
|
assert all([r == abs(v) for r, v in zip(res, range(-5, 5))])
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_shutdown_no_wait(self):
|
def test_shutdown_no_wait(self):
|
||||||
# Ensure that the executor cleans up the processes when calling
|
# Ensure that the executor cleans up the processes when calling
|
||||||
# shutdown with wait=False
|
# shutdown with wait=False
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
import unittest
|
import unittest
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
from test import support
|
from test import support
|
||||||
|
from test.support import warnings_helper
|
||||||
|
|
||||||
from .executor import ExecutorTest, mul
|
from .executor import ExecutorTest, mul
|
||||||
from .util import BaseTestCase, ThreadPoolMixin, setup_module
|
from .util import BaseTestCase, ThreadPoolMixin, setup_module
|
||||||
|
|
@ -53,6 +54,7 @@ def test_idle_thread_reuse(self):
|
||||||
@support.requires_fork()
|
@support.requires_fork()
|
||||||
@unittest.skipUnless(hasattr(os, 'register_at_fork'), 'need os.register_at_fork')
|
@unittest.skipUnless(hasattr(os, 'register_at_fork'), 'need os.register_at_fork')
|
||||||
@support.requires_resource('cpu')
|
@support.requires_resource('cpu')
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_hang_global_shutdown_lock(self):
|
def test_hang_global_shutdown_lock(self):
|
||||||
# bpo-45021: _global_shutdown_lock should be reinitialized in the child
|
# bpo-45021: _global_shutdown_lock should be reinitialized in the child
|
||||||
# process, otherwise it will never exit
|
# process, otherwise it will never exit
|
||||||
|
|
@ -68,6 +70,7 @@ def submit(pool):
|
||||||
|
|
||||||
@support.requires_fork()
|
@support.requires_fork()
|
||||||
@unittest.skipUnless(hasattr(os, 'register_at_fork'), 'need os.register_at_fork')
|
@unittest.skipUnless(hasattr(os, 'register_at_fork'), 'need os.register_at_fork')
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_process_fork_from_a_threadpool(self):
|
def test_process_fork_from_a_threadpool(self):
|
||||||
# bpo-43944: clear concurrent.futures.thread._threads_queues after fork,
|
# bpo-43944: clear concurrent.futures.thread._threads_queues after fork,
|
||||||
# otherwise child process will try to join parent thread
|
# otherwise child process will try to join parent thread
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
import unittest
|
import unittest
|
||||||
from concurrent import futures
|
from concurrent import futures
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import threading_helper
|
from test.support import threading_helper, warnings_helper
|
||||||
|
|
||||||
from .util import (
|
from .util import (
|
||||||
CANCELLED_FUTURE, CANCELLED_AND_NOTIFIED_FUTURE, EXCEPTION_FUTURE,
|
CANCELLED_FUTURE, CANCELLED_AND_NOTIFIED_FUTURE, EXCEPTION_FUTURE,
|
||||||
|
|
@ -22,6 +22,7 @@ def wait_and_raise(e):
|
||||||
|
|
||||||
|
|
||||||
class WaitTests:
|
class WaitTests:
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_20369(self):
|
def test_20369(self):
|
||||||
# See https://bugs.python.org/issue20369
|
# See https://bugs.python.org/issue20369
|
||||||
future = self.executor.submit(mul, 1, 2)
|
future = self.executor.submit(mul, 1, 2)
|
||||||
|
|
@ -30,7 +31,7 @@ def test_20369(self):
|
||||||
self.assertEqual({future}, done)
|
self.assertEqual({future}, done)
|
||||||
self.assertEqual(set(), not_done)
|
self.assertEqual(set(), not_done)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_first_completed(self):
|
def test_first_completed(self):
|
||||||
event = self.create_event()
|
event = self.create_event()
|
||||||
future1 = self.executor.submit(mul, 21, 2)
|
future1 = self.executor.submit(mul, 21, 2)
|
||||||
|
|
@ -47,6 +48,7 @@ def test_first_completed(self):
|
||||||
event.set()
|
event.set()
|
||||||
future2.result() # wait for job to finish
|
future2.result() # wait for job to finish
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_first_completed_some_already_completed(self):
|
def test_first_completed_some_already_completed(self):
|
||||||
event = self.create_event()
|
event = self.create_event()
|
||||||
future1 = self.executor.submit(event.wait)
|
future1 = self.executor.submit(event.wait)
|
||||||
|
|
@ -64,6 +66,7 @@ def test_first_completed_some_already_completed(self):
|
||||||
event.set()
|
event.set()
|
||||||
future1.result() # wait for job to finish
|
future1.result() # wait for job to finish
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_first_exception(self):
|
def test_first_exception(self):
|
||||||
event1 = self.create_event()
|
event1 = self.create_event()
|
||||||
event2 = self.create_event()
|
event2 = self.create_event()
|
||||||
|
|
@ -93,6 +96,7 @@ def wait_for_future1():
|
||||||
event2.set()
|
event2.set()
|
||||||
future3.result() # wait for job to finish
|
future3.result() # wait for job to finish
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_first_exception_some_already_complete(self):
|
def test_first_exception_some_already_complete(self):
|
||||||
event = self.create_event()
|
event = self.create_event()
|
||||||
future1 = self.executor.submit(divmod, 21, 0)
|
future1 = self.executor.submit(divmod, 21, 0)
|
||||||
|
|
@ -114,6 +118,7 @@ def test_first_exception_some_already_complete(self):
|
||||||
event.set()
|
event.set()
|
||||||
future2.result() # wait for job to finish
|
future2.result() # wait for job to finish
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_first_exception_one_already_failed(self):
|
def test_first_exception_one_already_failed(self):
|
||||||
event = self.create_event()
|
event = self.create_event()
|
||||||
future1 = self.executor.submit(event.wait)
|
future1 = self.executor.submit(event.wait)
|
||||||
|
|
@ -129,6 +134,7 @@ def test_first_exception_one_already_failed(self):
|
||||||
event.set()
|
event.set()
|
||||||
future1.result() # wait for job to finish
|
future1.result() # wait for job to finish
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_all_completed(self):
|
def test_all_completed(self):
|
||||||
future1 = self.executor.submit(divmod, 2, 0)
|
future1 = self.executor.submit(divmod, 2, 0)
|
||||||
future2 = self.executor.submit(mul, 2, 21)
|
future2 = self.executor.submit(mul, 2, 21)
|
||||||
|
|
@ -148,6 +154,7 @@ def test_all_completed(self):
|
||||||
future2]), finished)
|
future2]), finished)
|
||||||
self.assertEqual(set(), pending)
|
self.assertEqual(set(), pending)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_timeout(self):
|
def test_timeout(self):
|
||||||
short_timeout = 0.050
|
short_timeout = 0.050
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@
|
||||||
from concurrent.futures.process import _check_system_limits
|
from concurrent.futures.process import _check_system_limits
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import threading_helper
|
from test.support import threading_helper, warnings_helper
|
||||||
|
|
||||||
|
|
||||||
def create_future(state=PENDING, exception=None, result=None):
|
def create_future(state=PENDING, exception=None, result=None):
|
||||||
|
|
@ -51,7 +51,8 @@ def setUp(self):
|
||||||
max_workers=self.worker_count,
|
max_workers=self.worker_count,
|
||||||
mp_context=self.get_context(),
|
mp_context=self.get_context(),
|
||||||
**self.executor_kwargs)
|
**self.executor_kwargs)
|
||||||
self.manager = self.get_context().Manager()
|
with warnings_helper.ignore_fork_in_thread_deprecation_warnings():
|
||||||
|
self.manager = self.get_context().Manager()
|
||||||
else:
|
else:
|
||||||
self.executor = self.executor_type(
|
self.executor = self.executor_type(
|
||||||
max_workers=self.worker_count,
|
max_workers=self.worker_count,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
from test.fork_wait import ForkWait
|
from test.fork_wait import ForkWait
|
||||||
from test import support
|
from test import support
|
||||||
|
from test.support import warnings_helper
|
||||||
|
|
||||||
|
|
||||||
# Skip test if fork does not exist.
|
# Skip test if fork does not exist.
|
||||||
|
|
@ -19,6 +20,7 @@
|
||||||
|
|
||||||
|
|
||||||
class ForkTest(ForkWait):
|
class ForkTest(ForkWait):
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_threaded_import_lock_fork(self):
|
def test_threaded_import_lock_fork(self):
|
||||||
"""Check fork() in main thread works while a subthread is doing an import"""
|
"""Check fork() in main thread works while a subthread is doing an import"""
|
||||||
import_started = threading.Event()
|
import_started = threading.Event()
|
||||||
|
|
@ -61,7 +63,7 @@ def importer():
|
||||||
except OSError:
|
except OSError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_nested_import_lock_fork(self):
|
def test_nested_import_lock_fork(self):
|
||||||
"""Check fork() in main thread works while the main thread is doing an import"""
|
"""Check fork() in main thread works while the main thread is doing an import"""
|
||||||
exitcode = 42
|
exitcode = 42
|
||||||
|
|
|
||||||
|
|
@ -9,6 +9,8 @@
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
|
from test.support import warnings_helper
|
||||||
|
|
||||||
if not hasattr(select, "kqueue"):
|
if not hasattr(select, "kqueue"):
|
||||||
raise unittest.SkipTest("test works only on BSD")
|
raise unittest.SkipTest("test works only on BSD")
|
||||||
|
|
||||||
|
|
@ -257,6 +259,7 @@ def test_fd_non_inheritable(self):
|
||||||
self.addCleanup(kqueue.close)
|
self.addCleanup(kqueue.close)
|
||||||
self.assertEqual(os.get_inheritable(kqueue.fileno()), False)
|
self.assertEqual(os.get_inheritable(kqueue.fileno()), False)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@support.requires_fork()
|
@support.requires_fork()
|
||||||
def test_fork(self):
|
def test_fork(self):
|
||||||
# gh-110395: kqueue objects must be closed after fork
|
# gh-110395: kqueue objects must be closed after fork
|
||||||
|
|
|
||||||
|
|
@ -730,6 +730,7 @@ def remove_loop(fname, tries):
|
||||||
# based on os.fork existing because that is what users and this test use.
|
# based on os.fork existing because that is what users and this test use.
|
||||||
# This helps ensure that when fork exists (the important concept) that the
|
# This helps ensure that when fork exists (the important concept) that the
|
||||||
# register_at_fork mechanism is also present and used.
|
# register_at_fork mechanism is also present and used.
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@support.requires_fork()
|
@support.requires_fork()
|
||||||
@threading_helper.requires_working_threading()
|
@threading_helper.requires_working_threading()
|
||||||
@skip_if_asan_fork
|
@skip_if_asan_fork
|
||||||
|
|
@ -4045,6 +4046,7 @@ def test_config_queue_handler_invalid_config_does_not_create_multiprocessing_man
|
||||||
self._apply_simple_queue_listener_configuration(qspec)
|
self._apply_simple_queue_listener_configuration(qspec)
|
||||||
manager.assert_not_called()
|
manager.assert_not_called()
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@skip_if_tsan_fork
|
@skip_if_tsan_fork
|
||||||
@support.requires_subprocess()
|
@support.requires_subprocess()
|
||||||
@unittest.skipUnless(support.Py_DEBUG, "requires a debug build for testing"
|
@unittest.skipUnless(support.Py_DEBUG, "requires a debug build for testing"
|
||||||
|
|
@ -4067,6 +4069,7 @@ def test_config_reject_simple_queue_handler_multiprocessing_context(self):
|
||||||
with self.assertRaises(ValueError):
|
with self.assertRaises(ValueError):
|
||||||
self._apply_simple_queue_listener_configuration(qspec)
|
self._apply_simple_queue_listener_configuration(qspec)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@skip_if_tsan_fork
|
@skip_if_tsan_fork
|
||||||
@support.requires_subprocess()
|
@support.requires_subprocess()
|
||||||
@unittest.skipUnless(support.Py_DEBUG, "requires a debug build for testing"
|
@unittest.skipUnless(support.Py_DEBUG, "requires a debug build for testing"
|
||||||
|
|
@ -4107,6 +4110,7 @@ def _mpinit_issue121723(qspec, message_to_log):
|
||||||
# log a message (this creates a record put in the queue)
|
# log a message (this creates a record put in the queue)
|
||||||
logging.getLogger().info(message_to_log)
|
logging.getLogger().info(message_to_log)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@skip_if_tsan_fork
|
@skip_if_tsan_fork
|
||||||
@support.requires_subprocess()
|
@support.requires_subprocess()
|
||||||
def test_multiprocessing_queues(self):
|
def test_multiprocessing_queues(self):
|
||||||
|
|
@ -5337,6 +5341,7 @@ def _extract_logrecord_process_name(key, logMultiprocessing, conn=None):
|
||||||
else:
|
else:
|
||||||
return results
|
return results
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@skip_if_tsan_fork
|
@skip_if_tsan_fork
|
||||||
def test_multiprocessing(self):
|
def test_multiprocessing(self):
|
||||||
support.skip_if_broken_multiprocessing_synchronize()
|
support.skip_if_broken_multiprocessing_synchronize()
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
import io
|
import io
|
||||||
import tempfile
|
import tempfile
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import import_helper
|
from test.support import import_helper, warnings_helper
|
||||||
from test.support import os_helper
|
from test.support import os_helper
|
||||||
from test.support import refleak_helper
|
from test.support import refleak_helper
|
||||||
from test.support import socket_helper
|
from test.support import socket_helper
|
||||||
|
|
@ -1212,6 +1212,7 @@ def test_add_and_close(self):
|
||||||
self.assertEqual(contents, f.read())
|
self.assertEqual(contents, f.read())
|
||||||
self._box = self._factory(self._path)
|
self._box = self._factory(self._path)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@support.requires_fork()
|
@support.requires_fork()
|
||||||
@unittest.skipUnless(hasattr(socket, 'socketpair'), "Test needs socketpair().")
|
@unittest.skipUnless(hasattr(socket, 'socketpair'), "Test needs socketpair().")
|
||||||
def test_lock_conflict(self):
|
def test_lock_conflict(self):
|
||||||
|
|
|
||||||
|
|
@ -3518,6 +3518,7 @@ def test_getppid(self):
|
||||||
self.assertEqual(error, b'')
|
self.assertEqual(error, b'')
|
||||||
self.assertEqual(int(stdout), os.getpid())
|
self.assertEqual(int(stdout), os.getpid())
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def check_waitpid(self, code, exitcode, callback=None):
|
def check_waitpid(self, code, exitcode, callback=None):
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
# On Windows, os.spawnv() simply joins arguments with spaces:
|
# On Windows, os.spawnv() simply joins arguments with spaces:
|
||||||
|
|
@ -3620,30 +3621,35 @@ def create_args(self, *, with_env=False, use_bytes=False):
|
||||||
|
|
||||||
return program, args
|
return program, args
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnl')
|
@requires_os_func('spawnl')
|
||||||
def test_spawnl(self):
|
def test_spawnl(self):
|
||||||
program, args = self.create_args()
|
program, args = self.create_args()
|
||||||
exitcode = os.spawnl(os.P_WAIT, program, *args)
|
exitcode = os.spawnl(os.P_WAIT, program, *args)
|
||||||
self.assertEqual(exitcode, self.exitcode)
|
self.assertEqual(exitcode, self.exitcode)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnle')
|
@requires_os_func('spawnle')
|
||||||
def test_spawnle(self):
|
def test_spawnle(self):
|
||||||
program, args = self.create_args(with_env=True)
|
program, args = self.create_args(with_env=True)
|
||||||
exitcode = os.spawnle(os.P_WAIT, program, *args, self.env)
|
exitcode = os.spawnle(os.P_WAIT, program, *args, self.env)
|
||||||
self.assertEqual(exitcode, self.exitcode)
|
self.assertEqual(exitcode, self.exitcode)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnlp')
|
@requires_os_func('spawnlp')
|
||||||
def test_spawnlp(self):
|
def test_spawnlp(self):
|
||||||
program, args = self.create_args()
|
program, args = self.create_args()
|
||||||
exitcode = os.spawnlp(os.P_WAIT, program, *args)
|
exitcode = os.spawnlp(os.P_WAIT, program, *args)
|
||||||
self.assertEqual(exitcode, self.exitcode)
|
self.assertEqual(exitcode, self.exitcode)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnlpe')
|
@requires_os_func('spawnlpe')
|
||||||
def test_spawnlpe(self):
|
def test_spawnlpe(self):
|
||||||
program, args = self.create_args(with_env=True)
|
program, args = self.create_args(with_env=True)
|
||||||
exitcode = os.spawnlpe(os.P_WAIT, program, *args, self.env)
|
exitcode = os.spawnlpe(os.P_WAIT, program, *args, self.env)
|
||||||
self.assertEqual(exitcode, self.exitcode)
|
self.assertEqual(exitcode, self.exitcode)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnv')
|
@requires_os_func('spawnv')
|
||||||
def test_spawnv(self):
|
def test_spawnv(self):
|
||||||
program, args = self.create_args()
|
program, args = self.create_args()
|
||||||
|
|
@ -3654,30 +3660,35 @@ def test_spawnv(self):
|
||||||
exitcode = os.spawnv(os.P_WAIT, FakePath(program), args)
|
exitcode = os.spawnv(os.P_WAIT, FakePath(program), args)
|
||||||
self.assertEqual(exitcode, self.exitcode)
|
self.assertEqual(exitcode, self.exitcode)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnve')
|
@requires_os_func('spawnve')
|
||||||
def test_spawnve(self):
|
def test_spawnve(self):
|
||||||
program, args = self.create_args(with_env=True)
|
program, args = self.create_args(with_env=True)
|
||||||
exitcode = os.spawnve(os.P_WAIT, program, args, self.env)
|
exitcode = os.spawnve(os.P_WAIT, program, args, self.env)
|
||||||
self.assertEqual(exitcode, self.exitcode)
|
self.assertEqual(exitcode, self.exitcode)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnvp')
|
@requires_os_func('spawnvp')
|
||||||
def test_spawnvp(self):
|
def test_spawnvp(self):
|
||||||
program, args = self.create_args()
|
program, args = self.create_args()
|
||||||
exitcode = os.spawnvp(os.P_WAIT, program, args)
|
exitcode = os.spawnvp(os.P_WAIT, program, args)
|
||||||
self.assertEqual(exitcode, self.exitcode)
|
self.assertEqual(exitcode, self.exitcode)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnvpe')
|
@requires_os_func('spawnvpe')
|
||||||
def test_spawnvpe(self):
|
def test_spawnvpe(self):
|
||||||
program, args = self.create_args(with_env=True)
|
program, args = self.create_args(with_env=True)
|
||||||
exitcode = os.spawnvpe(os.P_WAIT, program, args, self.env)
|
exitcode = os.spawnvpe(os.P_WAIT, program, args, self.env)
|
||||||
self.assertEqual(exitcode, self.exitcode)
|
self.assertEqual(exitcode, self.exitcode)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnv')
|
@requires_os_func('spawnv')
|
||||||
def test_nowait(self):
|
def test_nowait(self):
|
||||||
program, args = self.create_args()
|
program, args = self.create_args()
|
||||||
pid = os.spawnv(os.P_NOWAIT, program, args)
|
pid = os.spawnv(os.P_NOWAIT, program, args)
|
||||||
support.wait_process(pid, exitcode=self.exitcode)
|
support.wait_process(pid, exitcode=self.exitcode)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnve')
|
@requires_os_func('spawnve')
|
||||||
def test_spawnve_bytes(self):
|
def test_spawnve_bytes(self):
|
||||||
# Test bytes handling in parse_arglist and parse_envlist (#28114)
|
# Test bytes handling in parse_arglist and parse_envlist (#28114)
|
||||||
|
|
@ -3685,18 +3696,21 @@ def test_spawnve_bytes(self):
|
||||||
exitcode = os.spawnve(os.P_WAIT, program, args, self.env)
|
exitcode = os.spawnve(os.P_WAIT, program, args, self.env)
|
||||||
self.assertEqual(exitcode, self.exitcode)
|
self.assertEqual(exitcode, self.exitcode)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnl')
|
@requires_os_func('spawnl')
|
||||||
def test_spawnl_noargs(self):
|
def test_spawnl_noargs(self):
|
||||||
program, __ = self.create_args()
|
program, __ = self.create_args()
|
||||||
self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, program)
|
self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, program)
|
||||||
self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, program, '')
|
self.assertRaises(ValueError, os.spawnl, os.P_NOWAIT, program, '')
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnle')
|
@requires_os_func('spawnle')
|
||||||
def test_spawnle_noargs(self):
|
def test_spawnle_noargs(self):
|
||||||
program, __ = self.create_args()
|
program, __ = self.create_args()
|
||||||
self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, program, {})
|
self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, program, {})
|
||||||
self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, program, '', {})
|
self.assertRaises(ValueError, os.spawnle, os.P_NOWAIT, program, '', {})
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnv')
|
@requires_os_func('spawnv')
|
||||||
def test_spawnv_noargs(self):
|
def test_spawnv_noargs(self):
|
||||||
program, __ = self.create_args()
|
program, __ = self.create_args()
|
||||||
|
|
@ -3705,6 +3719,7 @@ def test_spawnv_noargs(self):
|
||||||
self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, program, ('',))
|
self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, program, ('',))
|
||||||
self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, program, [''])
|
self.assertRaises(ValueError, os.spawnv, os.P_NOWAIT, program, [''])
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnve')
|
@requires_os_func('spawnve')
|
||||||
def test_spawnve_noargs(self):
|
def test_spawnve_noargs(self):
|
||||||
program, __ = self.create_args()
|
program, __ = self.create_args()
|
||||||
|
|
@ -3761,10 +3776,12 @@ def _test_invalid_env(self, spawn):
|
||||||
exitcode = spawn(os.P_WAIT, program, args, newenv)
|
exitcode = spawn(os.P_WAIT, program, args, newenv)
|
||||||
self.assertEqual(exitcode, 0)
|
self.assertEqual(exitcode, 0)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnve')
|
@requires_os_func('spawnve')
|
||||||
def test_spawnve_invalid_env(self):
|
def test_spawnve_invalid_env(self):
|
||||||
self._test_invalid_env(os.spawnve)
|
self._test_invalid_env(os.spawnve)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_os_func('spawnvpe')
|
@requires_os_func('spawnvpe')
|
||||||
def test_spawnvpe_invalid_env(self):
|
def test_spawnvpe_invalid_env(self):
|
||||||
self._test_invalid_env(os.spawnvpe)
|
self._test_invalid_env(os.spawnvpe)
|
||||||
|
|
@ -4881,6 +4898,7 @@ def test_posix_pty_functions(self):
|
||||||
self.addCleanup(os.close, son_fd)
|
self.addCleanup(os.close, son_fd)
|
||||||
self.assertEqual(os.ptsname(mother_fd), os.ttyname(son_fd))
|
self.assertEqual(os.ptsname(mother_fd), os.ttyname(son_fd))
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@unittest.skipUnless(hasattr(os, 'spawnl'), "need os.spawnl()")
|
@unittest.skipUnless(hasattr(os, 'spawnl'), "need os.spawnl()")
|
||||||
@support.requires_subprocess()
|
@support.requires_subprocess()
|
||||||
def test_pipe_spawnl(self):
|
def test_pipe_spawnl(self):
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import os_helper
|
from test.support import os_helper, warnings_helper
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# Some of the iOS tests need ctypes to operate.
|
# Some of the iOS tests need ctypes to operate.
|
||||||
|
|
@ -465,7 +465,7 @@ def test_mac_ver(self):
|
||||||
else:
|
else:
|
||||||
self.assertEqual(res[2], 'PowerPC')
|
self.assertEqual(res[2], 'PowerPC')
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@unittest.skipUnless(sys.platform == 'darwin', "OSX only test")
|
@unittest.skipUnless(sys.platform == 'darwin', "OSX only test")
|
||||||
def test_mac_ver_with_fork(self):
|
def test_mac_ver_with_fork(self):
|
||||||
# Issue7895: platform.mac_ver() crashes when using fork without exec
|
# Issue7895: platform.mac_ver() crashes when using fork without exec
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
import unittest
|
import unittest
|
||||||
from test.support import (
|
from test.support import (
|
||||||
is_android, is_apple_mobile, is_wasm32, reap_children, verbose
|
is_android, is_apple_mobile, is_wasm32, reap_children, verbose, warnings_helper
|
||||||
)
|
)
|
||||||
from test.support.import_helper import import_module
|
from test.support.import_helper import import_module
|
||||||
from test.support.os_helper import TESTFN, unlink
|
from test.support.os_helper import TESTFN, unlink
|
||||||
|
|
@ -194,6 +194,7 @@ def test_openpty(self):
|
||||||
s2 = _readline(master_fd)
|
s2 = _readline(master_fd)
|
||||||
self.assertEqual(b'For my pet fish, Eric.\n', normalize_output(s2))
|
self.assertEqual(b'For my pet fish, Eric.\n', normalize_output(s2))
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_fork(self):
|
def test_fork(self):
|
||||||
debug("calling pty.fork()")
|
debug("calling pty.fork()")
|
||||||
pid, master_fd = pty.fork()
|
pid, master_fd = pty.fork()
|
||||||
|
|
@ -295,6 +296,7 @@ def test_master_read(self):
|
||||||
|
|
||||||
self.assertEqual(data, b"")
|
self.assertEqual(data, b"")
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
def test_spawn_doesnt_hang(self):
|
def test_spawn_doesnt_hang(self):
|
||||||
self.addCleanup(unlink, TESTFN)
|
self.addCleanup(unlink, TESTFN)
|
||||||
with open(TESTFN, 'wb') as f:
|
with open(TESTFN, 'wb') as f:
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,8 @@
|
||||||
from fractions import Fraction
|
from fractions import Fraction
|
||||||
from collections import abc, Counter
|
from collections import abc, Counter
|
||||||
|
|
||||||
|
from test.support import warnings_helper
|
||||||
|
|
||||||
|
|
||||||
class MyIndex:
|
class MyIndex:
|
||||||
def __init__(self, value):
|
def __init__(self, value):
|
||||||
|
|
@ -1399,6 +1401,7 @@ def test__all__(self):
|
||||||
# tests validity but not completeness of the __all__ list
|
# tests validity but not completeness of the __all__ list
|
||||||
self.assertTrue(set(random.__all__) <= set(dir(random)))
|
self.assertTrue(set(random.__all__) <= set(dir(random)))
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@test.support.requires_fork()
|
@test.support.requires_fork()
|
||||||
def test_after_fork(self):
|
def test_after_fork(self):
|
||||||
# Test the global Random instance gets reseeded in child
|
# Test the global Random instance gets reseeded in child
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
from test.support import os_helper
|
from test.support import os_helper
|
||||||
from test.support import socket_helper
|
from test.support import socket_helper
|
||||||
from test.support import threading_helper
|
from test.support import threading_helper
|
||||||
|
from test.support import warnings_helper
|
||||||
|
|
||||||
|
|
||||||
test.support.requires("network")
|
test.support.requires("network")
|
||||||
|
|
@ -43,6 +44,7 @@ def receive(sock, n, timeout=test.support.SHORT_TIMEOUT):
|
||||||
raise RuntimeError("timed out on %r" % (sock,))
|
raise RuntimeError("timed out on %r" % (sock,))
|
||||||
|
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@test.support.requires_fork()
|
@test.support.requires_fork()
|
||||||
@contextlib.contextmanager
|
@contextlib.contextmanager
|
||||||
def simple_subprocess(testcase):
|
def simple_subprocess(testcase):
|
||||||
|
|
@ -173,6 +175,7 @@ def test_ThreadingTCPServer(self):
|
||||||
socketserver.StreamRequestHandler,
|
socketserver.StreamRequestHandler,
|
||||||
self.stream_examine)
|
self.stream_examine)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_forking
|
@requires_forking
|
||||||
def test_ForkingTCPServer(self):
|
def test_ForkingTCPServer(self):
|
||||||
with simple_subprocess(self):
|
with simple_subprocess(self):
|
||||||
|
|
@ -192,6 +195,7 @@ def test_ThreadingUnixStreamServer(self):
|
||||||
socketserver.StreamRequestHandler,
|
socketserver.StreamRequestHandler,
|
||||||
self.stream_examine)
|
self.stream_examine)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_unix_sockets
|
@requires_unix_sockets
|
||||||
@requires_forking
|
@requires_forking
|
||||||
def test_ForkingUnixStreamServer(self):
|
def test_ForkingUnixStreamServer(self):
|
||||||
|
|
@ -210,6 +214,7 @@ def test_ThreadingUDPServer(self):
|
||||||
socketserver.DatagramRequestHandler,
|
socketserver.DatagramRequestHandler,
|
||||||
self.dgram_examine)
|
self.dgram_examine)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_forking
|
@requires_forking
|
||||||
def test_ForkingUDPServer(self):
|
def test_ForkingUDPServer(self):
|
||||||
with simple_subprocess(self):
|
with simple_subprocess(self):
|
||||||
|
|
@ -229,6 +234,7 @@ def test_ThreadingUnixDatagramServer(self):
|
||||||
socketserver.DatagramRequestHandler,
|
socketserver.DatagramRequestHandler,
|
||||||
self.dgram_examine)
|
self.dgram_examine)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_unix_sockets
|
@requires_unix_sockets
|
||||||
@requires_forking
|
@requires_forking
|
||||||
def test_ForkingUnixDatagramServer(self):
|
def test_ForkingUnixDatagramServer(self):
|
||||||
|
|
@ -314,11 +320,13 @@ def test_threading_not_handled(self):
|
||||||
|
|
||||||
self.assertIs(cm.exc_type, SystemExit)
|
self.assertIs(cm.exc_type, SystemExit)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_forking
|
@requires_forking
|
||||||
def test_forking_handled(self):
|
def test_forking_handled(self):
|
||||||
ForkingErrorTestServer(ValueError)
|
ForkingErrorTestServer(ValueError)
|
||||||
self.check_result(handled=True)
|
self.check_result(handled=True)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@requires_forking
|
@requires_forking
|
||||||
def test_forking_not_handled(self):
|
def test_forking_not_handled(self):
|
||||||
ForkingErrorTestServer(SystemExit)
|
ForkingErrorTestServer(SystemExit)
|
||||||
|
|
|
||||||
|
|
@ -485,6 +485,7 @@ def test_check__all__(self):
|
||||||
|
|
||||||
self.assertRaises(AssertionError, support.check__all__, self, unittest)
|
self.assertRaises(AssertionError, support.check__all__, self, unittest)
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@unittest.skipUnless(hasattr(os, 'waitpid') and hasattr(os, 'WNOHANG'),
|
@unittest.skipUnless(hasattr(os, 'waitpid') and hasattr(os, 'WNOHANG'),
|
||||||
'need os.waitpid() and os.WNOHANG')
|
'need os.waitpid() and os.WNOHANG')
|
||||||
@support.requires_fork()
|
@support.requires_fork()
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@
|
||||||
from test.support.script_helper import (assert_python_ok, assert_python_failure,
|
from test.support.script_helper import (assert_python_ok, assert_python_failure,
|
||||||
interpreter_requires_environment)
|
interpreter_requires_environment)
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import force_not_colorized
|
from test.support import force_not_colorized, warnings_helper
|
||||||
from test.support import os_helper
|
from test.support import os_helper
|
||||||
from test.support import threading_helper
|
from test.support import threading_helper
|
||||||
|
|
||||||
|
|
@ -354,6 +354,7 @@ def fork_child(self):
|
||||||
# everything is fine
|
# everything is fine
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@support.requires_fork()
|
@support.requires_fork()
|
||||||
def test_fork(self):
|
def test_fork(self):
|
||||||
# check that tracemalloc is still working after fork
|
# check that tracemalloc is still working after fork
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@
|
||||||
from unittest import mock
|
from unittest import mock
|
||||||
|
|
||||||
from test import support
|
from test import support
|
||||||
from test.support import import_helper
|
from test.support import import_helper, warnings_helper
|
||||||
from test.support.script_helper import assert_python_ok
|
from test.support.script_helper import assert_python_ok
|
||||||
|
|
||||||
py_uuid = import_helper.import_fresh_module('uuid', blocked=['_uuid'])
|
py_uuid = import_helper.import_fresh_module('uuid', blocked=['_uuid'])
|
||||||
|
|
@ -1112,6 +1112,7 @@ def test_uuid8_uniqueness(self):
|
||||||
versions = {u.version for u in uuids}
|
versions = {u.version for u in uuids}
|
||||||
self.assertSetEqual(versions, {8})
|
self.assertSetEqual(versions, {8})
|
||||||
|
|
||||||
|
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
|
||||||
@support.requires_fork()
|
@support.requires_fork()
|
||||||
def testIssue8621(self):
|
def testIssue8621(self):
|
||||||
# On at least some versions of OSX self.uuid.uuid4 generates
|
# On at least some versions of OSX self.uuid.uuid4 generates
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,4 @@
|
||||||
|
With :option:`-Werror <-W>`, the DeprecationWarning emitted by :py:func:`os.fork`
|
||||||
|
and :py:func:`os.forkpty` in mutli-threaded processes is now raised as an exception.
|
||||||
|
Previously it was silently ignored.
|
||||||
|
Patch by Rani Pinchuk.
|
||||||
|
|
@ -8000,7 +8000,7 @@ os_register_at_fork_impl(PyObject *module, PyObject *before,
|
||||||
//
|
//
|
||||||
// This should only be called from the parent process after
|
// This should only be called from the parent process after
|
||||||
// PyOS_AfterFork_Parent().
|
// PyOS_AfterFork_Parent().
|
||||||
static void
|
static int
|
||||||
warn_about_fork_with_threads(const char* name)
|
warn_about_fork_with_threads(const char* name)
|
||||||
{
|
{
|
||||||
// It's not safe to issue the warning while the world is stopped, because
|
// It's not safe to issue the warning while the world is stopped, because
|
||||||
|
|
@ -8051,14 +8051,14 @@ warn_about_fork_with_threads(const char* name)
|
||||||
PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
|
PyObject *threading = PyImport_GetModule(&_Py_ID(threading));
|
||||||
if (!threading) {
|
if (!threading) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
PyObject *threading_active =
|
PyObject *threading_active =
|
||||||
PyObject_GetAttr(threading, &_Py_ID(_active));
|
PyObject_GetAttr(threading, &_Py_ID(_active));
|
||||||
if (!threading_active) {
|
if (!threading_active) {
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
Py_DECREF(threading);
|
Py_DECREF(threading);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
PyObject *threading_limbo =
|
PyObject *threading_limbo =
|
||||||
PyObject_GetAttr(threading, &_Py_ID(_limbo));
|
PyObject_GetAttr(threading, &_Py_ID(_limbo));
|
||||||
|
|
@ -8066,7 +8066,7 @@ warn_about_fork_with_threads(const char* name)
|
||||||
PyErr_Clear();
|
PyErr_Clear();
|
||||||
Py_DECREF(threading);
|
Py_DECREF(threading);
|
||||||
Py_DECREF(threading_active);
|
Py_DECREF(threading_active);
|
||||||
return;
|
return 0;
|
||||||
}
|
}
|
||||||
Py_DECREF(threading);
|
Py_DECREF(threading);
|
||||||
// Duplicating what threading.active_count() does but without holding
|
// Duplicating what threading.active_count() does but without holding
|
||||||
|
|
@ -8082,7 +8082,7 @@ warn_about_fork_with_threads(const char* name)
|
||||||
Py_DECREF(threading_limbo);
|
Py_DECREF(threading_limbo);
|
||||||
}
|
}
|
||||||
if (num_python_threads > 1) {
|
if (num_python_threads > 1) {
|
||||||
PyErr_WarnFormat(
|
return PyErr_WarnFormat(
|
||||||
PyExc_DeprecationWarning, 1,
|
PyExc_DeprecationWarning, 1,
|
||||||
#ifdef HAVE_GETPID
|
#ifdef HAVE_GETPID
|
||||||
"This process (pid=%d) is multi-threaded, "
|
"This process (pid=%d) is multi-threaded, "
|
||||||
|
|
@ -8094,8 +8094,8 @@ warn_about_fork_with_threads(const char* name)
|
||||||
getpid(),
|
getpid(),
|
||||||
#endif
|
#endif
|
||||||
name);
|
name);
|
||||||
PyErr_Clear();
|
|
||||||
}
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
#endif // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
|
#endif // HAVE_FORK1 || HAVE_FORKPTY || HAVE_FORK
|
||||||
|
|
||||||
|
|
@ -8134,7 +8134,9 @@ os_fork1_impl(PyObject *module)
|
||||||
/* parent: release the import lock. */
|
/* parent: release the import lock. */
|
||||||
PyOS_AfterFork_Parent();
|
PyOS_AfterFork_Parent();
|
||||||
// After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
|
// After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
|
||||||
warn_about_fork_with_threads("fork1");
|
if (warn_about_fork_with_threads("fork1") < 0) {
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
|
|
@ -8183,7 +8185,8 @@ os_fork_impl(PyObject *module)
|
||||||
/* parent: release the import lock. */
|
/* parent: release the import lock. */
|
||||||
PyOS_AfterFork_Parent();
|
PyOS_AfterFork_Parent();
|
||||||
// After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
|
// After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
|
||||||
warn_about_fork_with_threads("fork");
|
if (warn_about_fork_with_threads("fork") < 0)
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
errno = saved_errno;
|
errno = saved_errno;
|
||||||
|
|
@ -9040,7 +9043,8 @@ os_forkpty_impl(PyObject *module)
|
||||||
/* parent: release the import lock. */
|
/* parent: release the import lock. */
|
||||||
PyOS_AfterFork_Parent();
|
PyOS_AfterFork_Parent();
|
||||||
// After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
|
// After PyOS_AfterFork_Parent() starts the world to avoid deadlock.
|
||||||
warn_about_fork_with_threads("forkpty");
|
if (warn_about_fork_with_threads("forkpty") < 0)
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
if (pid == -1) {
|
if (pid == -1) {
|
||||||
return posix_error();
|
return posix_error();
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue