Skip to content

Commit 107e213

Browse files
Shawn Greenmanzagor
Shawn Greenman
authored andcommitted
Unlock the GIL when destroying DNP3Manager.
The ThreadPool owned by DNP3Manager causes a deadlock when it is destroyed without unlocking the GIL. By returning the DNP3Manager with a custom deleter which unlocks the GIL during destruction the pool can be deleted. Solution borrowed from: pybind/pybind11#1446
1 parent 7d0d314 commit 107e213

File tree

2 files changed

+14
-12
lines changed

2 files changed

+14
-12
lines changed

examples/master.py

+1
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,7 @@ def shutdown(self):
143143
del self.master
144144
del self.channel
145145
self.manager.Shutdown()
146+
del self.manager
146147

147148

148149
class MyLogger(openpal.ILogHandler):

src/asiodnp3/DNP3Manager.h

+13-12
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,22 @@
4040

4141
namespace py = pybind11;
4242

43+
template <typename T> void destroy_without_gil(T *ptr) {
44+
pybind11::gil_scoped_release nogil;
45+
delete ptr;
46+
}
47+
48+
template <typename T> struct unique_ptr_nogil_deleter {
49+
void operator()(T *ptr) { destroy_without_gil(ptr); }
50+
};
51+
4352
void bind_DNP3Manager(py::module &m)
4453
{
4554
// ----- class: asiodnp3::DNP3Manager -----
46-
py::class_<asiodnp3::DNP3Manager, std::shared_ptr<asiodnp3::DNP3Manager>>(m, "DNP3Manager",
55+
py::class_<asiodnp3::DNP3Manager,
56+
std::unique_ptr<asiodnp3::DNP3Manager,
57+
unique_ptr_nogil_deleter<
58+
asiodnp3::DNP3Manager>>>(m, "DNP3Manager",
4759
"Root DNP3 object used to create channels and sessions.")
4860

4961
.def(
@@ -71,22 +83,11 @@ void bind_DNP3Manager(py::module &m)
7183
py::arg("concurrencyHint"), py::arg("handler"), py::arg("onThreadStart"), py::arg("onThreadExit")
7284
)
7385

74-
.def(
75-
"__del__",
76-
[](asiodnp3::DNP3Manager &self)
77-
{
78-
self.~DNP3Manager();
79-
},
80-
"Destructor with gil_scoped_release.",
81-
py::call_guard<py::gil_scoped_release>()
82-
)
83-
8486
.def(
8587
"Shutdown",
8688
[](asiodnp3::DNP3Manager &self)
8789
{
8890
self.Shutdown();
89-
self.~DNP3Manager();
9091
},
9192
"Permanently shutdown the manager and all sub-objects that have been created. Stop the thread pool.",
9293
py::call_guard<py::gil_scoped_release>()

0 commit comments

Comments
 (0)