blob: 1307712ad363619a08dd82d380ab9dfbb4b7f303 [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
4from pybind11_tests import gil_scoped as m
5
6
7def _run_in_process(target, *args, **kwargs):
Yannick Jadoul085a2942019-01-03 19:41:10 +01008 """Runs target in process and returns its exitcode after 10s (None if still alive)."""
Borja Zarcoe2b884c2018-12-01 08:47:40 -05009 process = multiprocessing.Process(target=target, args=args, kwargs=kwargs)
10 process.daemon = True
11 try:
12 process.start()
Yannick Jadoul085a2942019-01-03 19:41:10 +010013 # Do not need to wait much, 10s should be more than enough.
14 process.join(timeout=10)
Borja Zarcoe2b884c2018-12-01 08:47:40 -050015 return process.exitcode
16 finally:
17 if process.is_alive():
18 process.terminate()
19
20
21def _python_to_cpp_to_python():
22 """Calls different C++ functions that come back to Python."""
23 class ExtendedVirtClass(m.VirtClass):
24 def virtual_func(self):
25 pass
26
27 def pure_virtual_func(self):
28 pass
29
30 extended = ExtendedVirtClass()
31 m.test_callback_py_obj(lambda: None)
32 m.test_callback_std_func(lambda: None)
33 m.test_callback_virtual_func(extended)
34 m.test_callback_pure_virtual_func(extended)
35
36
37def _python_to_cpp_to_python_from_threads(num_threads, parallel=False):
38 """Calls different C++ functions that come back to Python, from Python threads."""
39 threads = []
40 for _ in range(num_threads):
41 thread = threading.Thread(target=_python_to_cpp_to_python)
42 thread.daemon = True
43 thread.start()
44 if parallel:
45 threads.append(thread)
46 else:
47 thread.join()
48 for thread in threads:
49 thread.join()
50
51
52def test_python_to_cpp_to_python_from_thread():
53 """Makes sure there is no GIL deadlock when running in a thread.
54
55 It runs in a separate process to be able to stop and assert if it deadlocks.
56 """
57 assert _run_in_process(_python_to_cpp_to_python_from_threads, 1) == 0
58
59
60def test_python_to_cpp_to_python_from_thread_multiple_parallel():
61 """Makes sure there is no GIL deadlock when running in a thread multiple times in parallel.
62
63 It runs in a separate process to be able to stop and assert if it deadlocks.
64 """
65 assert _run_in_process(_python_to_cpp_to_python_from_threads, 8, parallel=True) == 0
66
67
68def test_python_to_cpp_to_python_from_thread_multiple_sequential():
69 """Makes sure there is no GIL deadlock when running in a thread multiple times sequentially.
70
71 It runs in a separate process to be able to stop and assert if it deadlocks.
72 """
73 assert _run_in_process(_python_to_cpp_to_python_from_threads, 8, parallel=False) == 0
74
75
76def test_python_to_cpp_to_python_from_process():
77 """Makes sure there is no GIL deadlock when using processes.
78
79 This test is for completion, but it was never an issue.
80 """
81 assert _run_in_process(_python_to_cpp_to_python) == 0
Saran Tunyasuvunakoolb60fd232019-07-15 15:47:02 +010082
83
84def test_cross_module_gil():
85 """Makes sure that the GIL can be acquired by another module from a GIL-released state."""
86 m.test_cross_module_gil() # Should not raise a SIGSEGV