test suite: ```py import time import multiprocessing class TestWhatever: def test_thing(self): def go(): time.sleep(2) ctx = multiprocessing.get_context("fork") proc = ctx.Process(target=go, args=()) proc.start() ``` Running as ``pytest test.py -n1``, output: ``` [classic@framework tmp2]$ pytest test.py -n1 ========================================================================================== test session starts ========================================================================================== platform linux -- Python 3.12.9, pytest-8.1.0, pluggy-1.4.0 rootdir: /home/classic/tmp2 plugins: xdist-3.4.0, anyio-4.1.0, random-0.2, repeat-0.9.3 1 worker [1 item] . [100%] =========================================================================================== warnings summary ============================================================================================ test.py::TestWhatever::test_thing /usr/lib64/python3.12/multiprocessing/popen_fork.py:66: DeprecationWarning: This process (pid=16078) is multi-threaded, use of fork() may lead to deadlocks in the child. self.pid = os.fork() -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html ===================================================================================== 1 passed, 1 warning in 2.19s ====================================================================================== ``` Per the author of this warning, multithreaded code is never safe if it also spawns using fork (see [discussion](https://github.com/python/cpython/pull/100229#issuecomment-2704803911)). However I cannot locate any threads running. Here's an extension of the example that lists out threads running, and I can find none that are not the "main" thread: conftest.py: ``` # conftest.py import threading import os import logging logging.basicConfig() logging.getLogger("main").setLevel(logging.INFO) class XDistHooks: def pytest_configure_node(self, node): for t in threading.enumerate(): logging.getLogger("main").info( f"THREAD FROM MAIN PROCESS {os.getpid()}: {t}\n") def pytest_configure(config): if config.pluginmanager.hasplugin("xdist"): config.pluginmanager.register(XDistHooks()) ``` test.py: ``` # test.py import time import os import multiprocessing import logging import threading logging.basicConfig() logging.getLogger("main").setLevel(logging.INFO) class TestWhatever: def test_thing(self): for t in threading.enumerate(): logging.getLogger("main").info( f"THREAD FROM CHILD PROCESS {os.getpid()} " f"(parent: {os.getppid()}): {t}\n") def go(): time.sleep(10) ctx = multiprocessing.get_context("fork") proc = ctx.Process(target=go, args=()) proc.start() ``` run output: ``` [classic@framework tmp]$ pytest test.py -s -p no:logging -n1 ========================================================================================== test session starts ========================================================================================== platform linux -- Python 3.12.9, pytest-8.1.0, pluggy-1.4.0 rootdir: /home/classic/tmp plugins: xdist-3.4.0, anyio-4.1.0, random-0.2, repeat-0.9.3 initialized: 1/1 workerINFO:main:THREAD FROM MAIN PROCESS 16341: <_MainThread(MainThread, started 139752741145472)> 1 worker [1 item] INFO:main:THREAD FROM CHILD PROCESS 16342 (parent: 16341): <_MainThread(MainThread, started 139984508341120)> . =========================================================================================== warnings summary ============================================================================================ test.py::TestWhatever::test_thing /usr/lib64/python3.12/multiprocessing/popen_fork.py:66: DeprecationWarning: This process (pid=16342) is multi-threaded, use of fork() may lead to deadlocks in the child. self.pid = os.fork() -- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html ===================================================================================== 1 passed, 1 warning in 10.17s ===================================================================================== ``` Basically I want to keep using fork() in my test code, since we are running functions inside the tests themselves in processes. Where is pytest-xdist and/or execnet spawning threads exactly (code is pretty opaque) and is this a bug in the python interpreter?