@@ -559,6 +559,39 @@ crucial that instances are deallocated on the C++ side to avoid memory leaks.
559559 py::class_<MyClass, std::unique_ptr<MyClass, py::nodelete>>(m, "MyClass")
560560 .def(py::init<>())
561561
562+ .. _destructors_that_call_python :
563+
564+ Destructors that call Python
565+ ============================
566+
567+ If a Python function is invoked from a C++ destructor, an exception may be thrown
568+ of type :class: `error_already_set `. If this error is thrown out of a class destructor,
569+ ``std::terminate() `` will be called, terminating the process. Class destructors
570+ must catch all exceptions of type :class: `error_already_set ` to discard the Python
571+ exception using :meth: `error_already_set::discard_as_unraisable `. (In addition,
572+ you should catch any C++ exceptions that may occur, if any, and deal with them.
573+ Since C++ exceptions are not Python exceptions, you cannot use ``discard_as_unraisable ``).
574+
575+ Every Python function, whether called through a pybind11 wrapper or through the
576+ Python C-API, should be treated as *possibly throwing *.
577+
578+ For more information, see :ref: `the documentation on exceptions <unraisable_exceptions >`.
579+
580+ .. code-block :: cpp
581+
582+ class MyClass {
583+ public:
584+ ~MyClass() {
585+ try {
586+ py::print("Even printing is dangerous in a destructor");
587+ py::exec("raise ValueError('This is an unraisable exception')");
588+ }
589+ catch (py::error_already_set &e) {
590+ e.discard_as_unraisable(__func__);
591+ };
592+ }
593+ };
594+
562595 .. _implicit_conversions :
563596
564597Implicit conversions
0 commit comments