mirror of
https://github.com/pybind/pybind11.git
synced 2024-11-23 05:35:13 +00:00
Improved implementation of error_already_set::~error_already_set()
C++ exceptions are destructed in the context of the code that catches them. At this point, the Python GIL may not be held, which could lead to crashes with the previous implementation. PyErr_Fetch and PyErr_Restore should always occur in pairs, which was not the case for the previous implementation. To clear the exception, the new approach uses PyErr_Restore && PyErr_Clear instead of simply decreasing the reference counts of the exception objects.
This commit is contained in:
parent
e72d958a5d
commit
099d6e9c48
@ -482,7 +482,16 @@ public:
|
|||||||
: std::runtime_error(e.what()), type(e.type), value(e.value),
|
: std::runtime_error(e.what()), type(e.type), value(e.value),
|
||||||
trace(e.trace) { e.type = e.value = e.trace = nullptr; }
|
trace(e.trace) { e.type = e.value = e.trace = nullptr; }
|
||||||
|
|
||||||
~error_already_set() { Py_XDECREF(type); Py_XDECREF(value); Py_XDECREF(trace); }
|
~error_already_set() {
|
||||||
|
if (value) {
|
||||||
|
PyGILState_STATE state = PyGILState_Ensure();
|
||||||
|
PyErr_Restore(type, value, trace);
|
||||||
|
PyErr_Clear();
|
||||||
|
PyGILState_Release(state);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
error_already_set& operator=(const error_already_set &) = delete;
|
||||||
|
|
||||||
/// Give the error back to Python
|
/// Give the error back to Python
|
||||||
void restore() { PyErr_Restore(type, value, trace); type = value = trace = nullptr; }
|
void restore() { PyErr_Restore(type, value, trace); type = value = trace = nullptr; }
|
||||||
|
Loading…
Reference in New Issue
Block a user