Skip to content

Commit 23afde8

Browse files
committed
Segmentation fault if run outside of function
1 parent e8ea93a commit 23afde8

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

python/pybind11/BUILD.bazel

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,12 @@ cc_binary(
7979
deps = [":include"],
8080
)
8181

82+
cc_binary(
83+
name = "test_gil_issue1723",
84+
srcs = ["custom_tests/test_gil_issue1723.cc"],
85+
deps = [":include"],
86+
)
87+
8288
cc_binary(
8389
name = "test_unique_ptr_stuff",
8490
srcs = ["custom_tests/test_unique_ptr_stuff.cc"],
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
// From: https://github.com/pybind/pybind11/issues/1723
2+
#include <iostream>
3+
#include <thread>
4+
#include <future>
5+
6+
#include <pybind11/embed.h>
7+
#include <pybind11/eval.h>
8+
#include <pybind11/pybind11.h>
9+
10+
namespace py = pybind11;
11+
12+
void hello() {
13+
std::cout << "hello\n";
14+
}
15+
16+
struct Executor {
17+
18+
void execute() {
19+
auto func = channel.get_future().get();
20+
func();
21+
}
22+
23+
explicit Executor(py::object callback)
24+
: callback(std::move(callback)),
25+
channel(),
26+
worker([this]{execute();}) {
27+
}
28+
29+
void run() {
30+
pybind11::gil_scoped_release release{};
31+
channel.set_value(callback);
32+
}
33+
34+
py::object callback;
35+
std::promise<py::object> channel;
36+
std::thread worker;
37+
38+
~Executor() {
39+
worker.join();
40+
}
41+
};
42+
43+
void init_module(py::module m) {
44+
m.def("hello", &hello, "Say hello");
45+
py::class_<Executor>(m, "Executor")
46+
.def(py::init<py::object>())
47+
.def("run", &Executor::run);
48+
}
49+
50+
int main(int, char**) {
51+
py::scoped_interpreter guard{};
52+
53+
py::module m("test_module");
54+
init_module(m);
55+
py::globals()["m"] = m;
56+
57+
py::print("[ Eval ]");
58+
py::exec(R"""(
59+
def bye():
60+
print('bye')
61+
62+
def main():
63+
pass
64+
65+
if True:
66+
m.hello()
67+
ex = m.Executor(bye)
68+
ex.run()
69+
70+
use_trace = False
71+
if use_trace:
72+
import sys, trace
73+
sys.stdout = sys.stderr
74+
tracer = trace.Trace(trace=1, count=0, ignoredirs=["/usr", sys.prefix])
75+
tracer.runfunc(main)
76+
else:
77+
main()
78+
)""");
79+
80+
py::print("[ Done ]");
81+
82+
return 0;
83+
}

0 commit comments

Comments
 (0)