1 from __future__
import annotations
11 from pybind11_tests
import gil_scoped
as m
23 m.test_callback_py_obj(
lambda:
None)
27 m.test_callback_std_func(
lambda:
None)
32 m.test_callback_virtual_func(extended)
37 m.test_callback_pure_virtual_func(extended)
41 """Makes sure that the GIL can be acquired by another module from a GIL-released state."""
42 m.test_cross_module_gil_released()
46 """Makes sure that the GIL can be acquired by another module from a GIL-acquired state."""
47 m.test_cross_module_gil_acquired()
51 """Makes sure that the GIL can be acquired/released by another module
52 from a GIL-released state using custom locking logic."""
53 m.test_cross_module_gil_inner_custom_released()
57 """Makes sure that the GIL can be acquired/acquired by another module
58 from a GIL-acquired state using custom locking logic."""
59 m.test_cross_module_gil_inner_custom_acquired()
63 """Makes sure that the GIL can be acquired/released by another module
64 from a GIL-released state using pybind11 locking logic."""
65 m.test_cross_module_gil_inner_pybind11_released()
69 """Makes sure that the GIL can be acquired/acquired by another module
70 from a GIL-acquired state using pybind11 locking logic."""
71 m.test_cross_module_gil_inner_pybind11_acquired()
74 @pytest.mark.skipif(sys.platform.startswith(
"emscripten"), reason=
"Requires threads")
76 """Makes sure that the GIL can be nested acquired/released by another module
77 from a GIL-released state using custom locking logic."""
78 m.test_cross_module_gil_nested_custom_released()
81 @pytest.mark.skipif(sys.platform.startswith(
"emscripten"), reason=
"Requires threads")
83 """Makes sure that the GIL can be nested acquired/acquired by another module
84 from a GIL-acquired state using custom locking logic."""
85 m.test_cross_module_gil_nested_custom_acquired()
88 @pytest.mark.skipif(sys.platform.startswith(
"emscripten"), reason=
"Requires threads")
90 """Makes sure that the GIL can be nested acquired/released by another module
91 from a GIL-released state using pybind11 locking logic."""
92 m.test_cross_module_gil_nested_pybind11_released()
95 @pytest.mark.skipif(sys.platform.startswith(
"emscripten"), reason=
"Requires threads")
97 """Makes sure that the GIL can be nested acquired/acquired by another module
98 from a GIL-acquired state using pybind11 locking logic."""
99 m.test_cross_module_gil_nested_pybind11_acquired()
103 assert m.test_release_acquire(0xAB) ==
"171"
107 assert m.test_nested_acquire(0xAB) ==
"171"
110 @pytest.mark.skipif(sys.platform.startswith(
"emscripten"), reason=
"Requires threads")
112 for bits
in range(16 * 8):
113 internals_ids = m.test_multi_acquire_release_cross_module(bits)
114 assert len(internals_ids) == 2
if bits % 8
else 1
118 VARS_BEFORE_ALL_BASIC_TESTS =
dict(vars())
120 test_callback_py_obj,
121 test_callback_std_func,
122 test_callback_virtual_func,
123 test_callback_pure_virtual_func,
124 test_cross_module_gil_released,
125 test_cross_module_gil_acquired,
126 test_cross_module_gil_inner_custom_released,
127 test_cross_module_gil_inner_custom_acquired,
128 test_cross_module_gil_inner_pybind11_released,
129 test_cross_module_gil_inner_pybind11_acquired,
130 test_cross_module_gil_nested_custom_released,
131 test_cross_module_gil_nested_custom_acquired,
132 test_cross_module_gil_nested_pybind11_released,
133 test_cross_module_gil_nested_pybind11_acquired,
134 test_release_acquire,
136 test_multi_acquire_release_cross_module,
142 for key, value
in VARS_BEFORE_ALL_BASIC_TESTS.items():
143 if not key.startswith(
"test_"):
145 assert value
in ALL_BASIC_TESTS
147 assert len(ALL_BASIC_TESTS) == num_found
151 m.intentional_deadlock()
154 ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK = ALL_BASIC_TESTS + (_intentional_deadlock,)
158 test_fn = target
if len(args) == 0
else args[0]
160 timeout = 0.1
if test_fn
is _intentional_deadlock
else 10
161 process = multiprocessing.Process(target=target, args=args, kwargs=kwargs)
162 process.daemon =
True
164 t_start = time.time()
168 "\nprocess.pid STARTED", process.pid, (sys.argv, target, args, kwargs)
170 print(f
"COPY-PASTE-THIS: gdb {sys.argv[0]} -p {process.pid}", flush=
True)
171 process.join(timeout=timeout)
173 print(
"\nprocess.pid JOINED", process.pid, flush=
True)
174 t_delta = time.time() - t_start
175 if process.exitcode == 66
and m.defined_THREAD_SANITIZER:
180 "ThreadSanitizer: starting new threads after multi-threaded fork is not supported."
182 elif test_fn
is _intentional_deadlock:
183 assert process.exitcode
is None
186 if process.exitcode
is None:
187 assert t_delta > 0.9 * timeout
188 msg =
"DEADLOCK, most likely, exactly what this test is meant to detect."
189 if env.PYPY
and env.WIN:
191 raise RuntimeError(msg)
192 return process.exitcode
194 if process.is_alive():
200 for _
in range(num_threads):
201 thread = threading.Thread(target=test_fn)
205 threads.append(thread)
208 for thread
in threads:
212 @pytest.mark.skipif(sys.platform.startswith(
"emscripten"), reason=
"Requires threads")
213 @pytest.mark.parametrize(
"test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
215 """Makes sure there is no GIL deadlock when running in a thread.
217 It runs in a separate process to be able to stop and assert if it deadlocks.
219 assert _run_in_process(_run_in_threads, test_fn, num_threads=1, parallel=
False) == 0
222 @pytest.mark.skipif(sys.platform.startswith(
"emscripten"), reason=
"Requires threads")
223 @pytest.mark.parametrize(
"test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
225 """Makes sure there is no GIL deadlock when running in a thread multiple times in parallel.
227 It runs in a separate process to be able to stop and assert if it deadlocks.
229 assert _run_in_process(_run_in_threads, test_fn, num_threads=8, parallel=
True) == 0
232 @pytest.mark.skipif(sys.platform.startswith(
"emscripten"), reason=
"Requires threads")
233 @pytest.mark.parametrize(
"test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
235 """Makes sure there is no GIL deadlock when running in a thread multiple times sequentially.
237 It runs in a separate process to be able to stop and assert if it deadlocks.
239 assert _run_in_process(_run_in_threads, test_fn, num_threads=8, parallel=
False) == 0
242 @pytest.mark.skipif(sys.platform.startswith(
"emscripten"), reason=
"Requires threads")
243 @pytest.mark.parametrize(
"test_fn", ALL_BASIC_TESTS_PLUS_INTENTIONAL_DEADLOCK)
245 """Makes sure there is no GIL deadlock when using processes.
247 This test is for completion, but it was never an issue.