blob: c85eb7c72b0173e8c1fce1951572ca4f7102fb2c [file] [log] [blame]
Henry Schreinerd8c7ee02020-07-20 13:35:21 -04001# -*- coding: utf-8 -*-
Borja Zarcoe2b884c2018-12-01 08:47:40 -05002import multiprocessing
3import threading
Henry Schreiner110e6c12020-08-20 11:58:34 -04004
5import pytest
6
7import env # noqa: F401
8
Borja Zarcoe2b884c2018-12-01 08:47:40 -05009from pybind11_tests import gil_scoped as m
10
11
12def _run_in_process(target, *args, **kwargs):
Yannick Jadoul085a2942019-01-03 19:41:10 +010013 """Runs target in process and returns its exitcode after 10s (None if still alive)."""
Borja Zarcoe2b884c2018-12-01 08:47:40 -050014 process = multiprocessing.Process(target=target, args=args, kwargs=kwargs)
15 process.daemon = True
16 try:
17 process.start()
Yannick Jadoul085a2942019-01-03 19:41:10 +010018 # Do not need to wait much, 10s should be more than enough.
19 process.join(timeout=10)
Borja Zarcoe2b884c2018-12-01 08:47:40 -050020 return process.exitcode
21 finally:
22 if process.is_alive():
23 process.terminate()
24
25
26def _python_to_cpp_to_python():
27 """Calls different C++ functions that come back to Python."""
28 class ExtendedVirtClass(m.VirtClass):
29 def virtual_func(self):
30 pass
31
32 def pure_virtual_func(self):
33 pass
34
35 extended = ExtendedVirtClass()
36 m.test_callback_py_obj(lambda: None)
37 m.test_callback_std_func(lambda: None)
38 m.test_callback_virtual_func(extended)
39 m.test_callback_pure_virtual_func(extended)
40
41
42def _python_to_cpp_to_python_from_threads(num_threads, parallel=False):
43 """Calls different C++ functions that come back to Python, from Python threads."""
44 threads = []
45 for _ in range(num_threads):
46 thread = threading.Thread(target=_python_to_cpp_to_python)
47 thread.daemon = True
48 thread.start()
49 if parallel:
50 threads.append(thread)
51 else:
52 thread.join()
53 for thread in threads:
54 thread.join()
55
56
57def test_python_to_cpp_to_python_from_thread():
58 """Makes sure there is no GIL deadlock when running in a thread.
59
60 It runs in a separate process to be able to stop and assert if it deadlocks.
61 """
62 assert _run_in_process(_python_to_cpp_to_python_from_threads, 1) == 0
63
64
Henry Schreiner110e6c12020-08-20 11:58:34 -040065# TODO: FIXME
66@pytest.mark.xfail("env.PY > (3,8) and env.MACOS", strict=False)
Borja Zarcoe2b884c2018-12-01 08:47:40 -050067def test_python_to_cpp_to_python_from_thread_multiple_parallel():
68 """Makes sure there is no GIL deadlock when running in a thread multiple times in parallel.
69
70 It runs in a separate process to be able to stop and assert if it deadlocks.
71 """
72 assert _run_in_process(_python_to_cpp_to_python_from_threads, 8, parallel=True) == 0
73
74
75def test_python_to_cpp_to_python_from_thread_multiple_sequential():
76 """Makes sure there is no GIL deadlock when running in a thread multiple times sequentially.
77
78 It runs in a separate process to be able to stop and assert if it deadlocks.
79 """
80 assert _run_in_process(_python_to_cpp_to_python_from_threads, 8, parallel=False) == 0
81
82
Henry Schreiner110e6c12020-08-20 11:58:34 -040083# TODO: FIXME
84@pytest.mark.xfail("env.PY > (3,8) and env.MACOS", strict=False)
Borja Zarcoe2b884c2018-12-01 08:47:40 -050085def test_python_to_cpp_to_python_from_process():
86 """Makes sure there is no GIL deadlock when using processes.
87
88 This test is for completion, but it was never an issue.
89 """
90 assert _run_in_process(_python_to_cpp_to_python) == 0
Saran Tunyasuvunakoolb60fd232019-07-15 15:47:02 +010091
92
93def test_cross_module_gil():
94 """Makes sure that the GIL can be acquired by another module from a GIL-released state."""
95 m.test_cross_module_gil() # Should not raise a SIGSEGV