diff --git a/include/pybind11/pytypes.h b/include/pybind11/pytypes.h index 76e915cca..87ddf4838 100644 --- a/include/pybind11/pytypes.h +++ b/include/pybind11/pytypes.h @@ -320,11 +320,11 @@ NAMESPACE_END(detail) /// thrown to propagate python-side errors back through C++ which can either be caught manually or /// else falls back to the function dispatcher (which then raises the captured error back to /// python). -class error_already_set : public std::exception { +class error_already_set : public std::runtime_error { public: /// Constructs a new exception from the current Python error indicator, if any. The current /// Python error indicator will be cleared. - error_already_set() : std::exception() { + error_already_set() : std::runtime_error("") { PyErr_Fetch(&m_type.ptr(), &m_value.ptr(), &m_trace.ptr()); } @@ -334,12 +334,16 @@ public: inline ~error_already_set(); virtual const char* what() const noexcept { - if (m_lazy_what.empty()) { - if (m_type || m_value || m_trace) - PyErr_NormalizeException(&m_type.ptr(), &m_value.ptr(), &m_trace.ptr()); - m_lazy_what = detail::error_string(m_type.ptr(), m_value.ptr(), m_trace.ptr()); + try { + if (m_lazy_what.empty()) { + if (m_type || m_value || m_trace) + PyErr_NormalizeException(&m_type.ptr(), &m_value.ptr(), &m_trace.ptr()); + m_lazy_what = detail::error_string(m_type.ptr(), m_value.ptr(), m_trace.ptr()); + } + return m_lazy_what.c_str(); + } catch (...) { + return "Unknown internal error occurred"; } - return m_lazy_what.c_str(); } /// Give the currently-held error back to Python, if any. If there is currently a Python error diff --git a/tests/test_exceptions.cpp b/tests/test_exceptions.cpp index a3fb7b8e9..d30139037 100644 --- a/tests/test_exceptions.cpp +++ b/tests/test_exceptions.cpp @@ -157,7 +157,7 @@ TEST_SUBMODULE(exceptions, m) { PyErr_SetString(PyExc_ValueError, "foo"); try { throw py::error_already_set(); - } catch (const py::error_already_set& e) { + } catch (const std::runtime_error& e) { if ((err && e.what() != std::string("ValueError: foo")) || (!err && e.what() != std::string("Unknown internal error occurred"))) {