mirror of
https://github.com/pybind/pybind11.git
synced 2025-01-19 17:32:37 +00:00
Fix handling of Python exceptions during module initialization (#657)
Fixes #656. Before this commit, the problematic sequence was: 1. `catch (const std::exception &e)` gets a Python exception, i.e. `error_already_set`. 2. `PyErr_SetString(PyExc_ImportError, e.what())` sets an `ImportError`. 3. `~error_already_set()` now runs, but `gil_scoped_acquire` fails due to an unhandled `ImportError` (which was just set in step 2). This commit adds a separate catch block for Python exceptions which just clears the Python error state a little earlier and replaces it with an `ImportError`, thus making sure that there is only a single Python exception in flight at a time. (After step 2 in the sequence above, there were effectively two Python expections set.)
This commit is contained in:
parent
1eaacd19f6
commit
d534bd670e
@ -189,6 +189,10 @@ extern "C" {
|
|||||||
} \
|
} \
|
||||||
try { \
|
try { \
|
||||||
return pybind11_init(); \
|
return pybind11_init(); \
|
||||||
|
} catch (pybind11::error_already_set &e) { \
|
||||||
|
e.clear(); \
|
||||||
|
PyErr_SetString(PyExc_ImportError, e.what()); \
|
||||||
|
return nullptr; \
|
||||||
} catch (const std::exception &e) { \
|
} catch (const std::exception &e) { \
|
||||||
PyErr_SetString(PyExc_ImportError, e.what()); \
|
PyErr_SetString(PyExc_ImportError, e.what()); \
|
||||||
return nullptr; \
|
return nullptr; \
|
||||||
@ -561,6 +565,9 @@ public:
|
|||||||
/// 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; }
|
||||||
|
|
||||||
|
/// Clear the held Python error state (the C++ `what()` message remains intact)
|
||||||
|
void clear() { restore(); PyErr_Clear(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PyObject *type, *value, *trace;
|
PyObject *type, *value, *trace;
|
||||||
};
|
};
|
||||||
|
@ -1884,8 +1884,7 @@ class gil_scoped_release { };
|
|||||||
error_already_set::~error_already_set() {
|
error_already_set::~error_already_set() {
|
||||||
if (value) {
|
if (value) {
|
||||||
gil_scoped_acquire gil;
|
gil_scoped_acquire gil;
|
||||||
PyErr_Restore(type, value, trace);
|
clear();
|
||||||
PyErr_Clear();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user