Commit 9c18a74e by Ralf W. Grosse-Kunstleve Committed by GitHub

Use `multiprocessing` `start_method` `"forkserver"` (#4306)

* Use `multiprocessing` `start_method` `"forkserver"`

Alternative to PR #4305

* Add link to comment under PR #4105

* Unconditionally `pytest.skip("DEADLOCK")` for PyPy Windows

* Remove `SKIP_IF_DEADLOCK` entirely, for simplicity. Hopefully this PR will resolve the deadlocks for good.

* Add "In a nutshell" comment, in response to request by @EricCousineau-TRI
parent 48949222
...@@ -7,6 +7,8 @@ Adds docstring and exceptions message sanitizers. ...@@ -7,6 +7,8 @@ Adds docstring and exceptions message sanitizers.
import contextlib import contextlib
import difflib import difflib
import gc import gc
import multiprocessing
import os
import re import re
import textwrap import textwrap
...@@ -15,6 +17,16 @@ import pytest ...@@ -15,6 +17,16 @@ import pytest
# Early diagnostic for failed imports # Early diagnostic for failed imports
import pybind11_tests import pybind11_tests
if os.name != "nt":
# Full background: https://github.com/pybind/pybind11/issues/4105#issuecomment-1301004592
# In a nutshell: fork() after starting threads == flakiness in the form of deadlocks.
# It is actually a well-known pitfall, unfortunately without guard rails.
# "forkserver" is more performant than "spawn" (~9s vs ~13s for tests/test_gil_scoped.py,
# visit the issuecomment link above for details).
# Windows does not have fork() and the associated pitfall, therefore it is best left
# running with defaults.
multiprocessing.set_start_method("forkserver")
_long_marker = re.compile(r"([0-9])L") _long_marker = re.compile(r"([0-9])L")
_hexadecimal = re.compile(r"0x[0-9a-fA-F]+") _hexadecimal = re.compile(r"0x[0-9a-fA-F]+")
......
...@@ -5,6 +5,7 @@ import time ...@@ -5,6 +5,7 @@ import time
import pytest import pytest
import env
from pybind11_tests import gil_scoped as m from pybind11_tests import gil_scoped as m
...@@ -144,7 +145,6 @@ def _intentional_deadlock(): ...@@ -144,7 +145,6 @@ def _intentional_deadlock():
ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK = ALL_BASIC_TESTS + (_intentional_deadlock,) ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK = ALL_BASIC_TESTS + (_intentional_deadlock,)
SKIP_IF_DEADLOCK = True # See PR #4216
def _run_in_process(target, *args, **kwargs): def _run_in_process(target, *args, **kwargs):
...@@ -181,7 +181,7 @@ def _run_in_process(target, *args, **kwargs): ...@@ -181,7 +181,7 @@ def _run_in_process(target, *args, **kwargs):
elif process.exitcode is None: elif process.exitcode is None:
assert t_delta > 0.9 * timeout assert t_delta > 0.9 * timeout
msg = "DEADLOCK, most likely, exactly what this test is meant to detect." msg = "DEADLOCK, most likely, exactly what this test is meant to detect."
if SKIP_IF_DEADLOCK: if env.PYPY and env.WIN:
pytest.skip(msg) pytest.skip(msg)
raise RuntimeError(msg) raise RuntimeError(msg)
return process.exitcode return process.exitcode
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment