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:
Rani Pinchuk 2025-08-26 15:33:21 +02:00 committed by GitHub
parent f60f8225ed
commit fd8f42d3d1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
27 changed files with 390 additions and 69 deletions

View file

@ -15,7 +15,7 @@
from unittest import mock
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 wait_process
from test.support import hashlib_helper
@ -1183,29 +1183,31 @@ async def runner():
class TestFork(unittest.IsolatedAsyncioTestCase):
async def test_fork_not_share_event_loop(self):
# The forked process should not share the event loop with the parent
loop = asyncio.get_running_loop()
r, w = os.pipe()
self.addCleanup(os.close, r)
self.addCleanup(os.close, w)
pid = os.fork()
if pid == 0:
# child
try:
loop = asyncio.get_event_loop()
os.write(w, b'LOOP:' + str(id(loop)).encode())
except RuntimeError:
os.write(w, b'NO LOOP')
except BaseException as e:
os.write(w, b'ERROR:' + ascii(e).encode())
finally:
os._exit(0)
else:
# parent
result = os.read(r, 100)
self.assertEqual(result, b'NO LOOP')
wait_process(pid, exitcode=0)
with warnings_helper.ignore_fork_in_thread_deprecation_warnings():
# The forked process should not share the event loop with the parent
loop = asyncio.get_running_loop()
r, w = os.pipe()
self.addCleanup(os.close, r)
self.addCleanup(os.close, w)
pid = os.fork()
if pid == 0:
# child
try:
loop = asyncio.get_event_loop()
os.write(w, b'LOOP:' + str(id(loop)).encode())
except RuntimeError:
os.write(w, b'NO LOOP')
except BaseException as e:
os.write(w, b'ERROR:' + ascii(e).encode())
finally:
os._exit(0)
else:
# parent
result = os.read(r, 100)
self.assertEqual(result, b'NO LOOP')
wait_process(pid, exitcode=0)
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
@hashlib_helper.requires_hashdigest('md5')
@support.skip_if_sanitizer("TSAN doesn't support threads after fork", thread=True)
def test_fork_signal_handling(self):
@ -1253,6 +1255,7 @@ async def func():
self.assertFalse(parent_handled.is_set())
self.assertTrue(child_handled.is_set())
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
@hashlib_helper.requires_hashdigest('md5')
@support.skip_if_sanitizer("TSAN doesn't support threads after fork", thread=True)
def test_fork_asyncio_run(self):
@ -1273,6 +1276,7 @@ async def child_main():
self.assertEqual(result.value, 42)
@warnings_helper.ignore_fork_in_thread_deprecation_warnings()
@hashlib_helper.requires_hashdigest('md5')
@support.skip_if_sanitizer("TSAN doesn't support threads after fork", thread=True)
def test_fork_asyncio_subprocess(self):