blob: 6e7fe9f4c0235f2e72b8b91de83417e135eee75e [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
Henry Schreiner3a89bff2020-08-31 14:28:07 -040057# TODO: FIXME, sometimes returns -11 instead of 0
Henry Fredrick Schreinere3774b72020-09-16 22:03:06 -040058@pytest.mark.xfail("env.PY >= (3,9) and env.MACOS", strict=False)
Borja Zarcoe2b884c2018-12-01 08:47:40 -050059def test_python_to_cpp_to_python_from_thread():
60 """Makes sure there is no GIL deadlock when running in a thread.
61
62 It runs in a separate process to be able to stop and assert if it deadlocks.
63 """
64 assert _run_in_process(_python_to_cpp_to_python_from_threads, 1) == 0
65
66
Henry Schreiner110e6c12020-08-20 11:58:34 -040067# TODO: FIXME
Henry Fredrick Schreinere3774b72020-09-16 22:03:06 -040068@pytest.mark.xfail("env.PY >= (3,9) and env.MACOS", strict=False)
Borja Zarcoe2b884c2018-12-01 08:47:40 -050069def test_python_to_cpp_to_python_from_thread_multiple_parallel():
70 """Makes sure there is no GIL deadlock when running in a thread multiple times in parallel.
71
72 It runs in a separate process to be able to stop and assert if it deadlocks.
73 """
74 assert _run_in_process(_python_to_cpp_to_python_from_threads, 8, parallel=True) == 0
75
76
Henry Schreiner3a89bff2020-08-31 14:28:07 -040077# TODO: FIXME
Henry Fredrick Schreinere3774b72020-09-16 22:03:06 -040078@pytest.mark.xfail("env.PY >= (3,9) and env.MACOS", strict=False)
Borja Zarcoe2b884c2018-12-01 08:47:40 -050079def test_python_to_cpp_to_python_from_thread_multiple_sequential():
80 """Makes sure there is no GIL deadlock when running in a thread multiple times sequentially.
81
82 It runs in a separate process to be able to stop and assert if it deadlocks.
83 """
84 assert _run_in_process(_python_to_cpp_to_python_from_threads, 8, parallel=False) == 0
85
86
Henry Schreiner110e6c12020-08-20 11:58:34 -040087# TODO: FIXME
Henry Fredrick Schreinere3774b72020-09-16 22:03:06 -040088@pytest.mark.xfail("env.PY >= (3,9) and env.MACOS", strict=False)
Borja Zarcoe2b884c2018-12-01 08:47:40 -050089def test_python_to_cpp_to_python_from_process():
90 """Makes sure there is no GIL deadlock when using processes.
91
92 This test is for completion, but it was never an issue.
93 """
94 assert _run_in_process(_python_to_cpp_to_python) == 0
Saran Tunyasuvunakoolb60fd232019-07-15 15:47:02 +010095
96
97def test_cross_module_gil():
98 """Makes sure that the GIL can be acquired by another module from a GIL-released state."""
99 m.test_cross_module_gil() # Should not raise a SIGSEGV