Add and document py::error_already_set::discard_as_unraisable()

To deal with exceptions that hit destructors or other noexcept functions.

Includes fixes to support Python 2.7 and extends documentation on
error handling.

@virtuald and @YannickJadoul both contributed to this PR.
diff --git a/docs/advanced/classes.rst b/docs/advanced/classes.rst
index 031484c..e8940d8 100644
--- a/docs/advanced/classes.rst
+++ b/docs/advanced/classes.rst
@@ -559,6 +559,44 @@
     py::class_<MyClass, std::unique_ptr<MyClass, py::nodelete>>(m, "MyClass")
         .def(py::init<>())
 
+.. _destructors_that_call_python:
+
+Destructors that call Python
+============================
+
+If a Python function is invoked from a C++ destructor, an exception may be thrown
+of type :class:`error_already_set`. If this error is thrown out of a class destructor,
+``std::terminate()`` will be called, terminating the process. Class destructors
+must catch all exceptions of type :class:`error_already_set` to discard the Python
+exception using :func:`error_already_set::discard_as_unraisable`.
+
+Every Python function should be treated as *possibly throwing*. When a Python generator
+stops yielding items, Python will throw a ``StopIteration`` exception, which can pass
+though C++ destructors if the generator's stack frame holds the last reference to C++
+objects.
+
+For more information, see :ref:`the documentation on exceptions <unraisable_exceptions>`.
+
+.. code-block:: cpp
+
+    class MyClass {
+    public:
+        ~MyClass() {
+            try {
+                py::print("Even printing is dangerous in a destructor");
+                py::exec("raise ValueError('This is an unraisable exception')");
+            } catch (py::error_already_set &e) {
+                // error_context should be information about where/why the occurred,
+                // e.g. use __func__ to get the name of the current function
+                e.discard_as_unraisable(__func__);
+            }
+        }
+    };
+
+.. note::
+
+    pybind11 does not support C++ destructors marked ``noexcept(false)``.
+
 .. _implicit_conversions:
 
 Implicit conversions
diff --git a/docs/advanced/exceptions.rst b/docs/advanced/exceptions.rst
index 75ad7f7..4fa53ca 100644
--- a/docs/advanced/exceptions.rst
+++ b/docs/advanced/exceptions.rst
@@ -53,9 +53,15 @@
 |                                      | a Python exception back to Python.   |
 +--------------------------------------+--------------------------------------+
 
-When a Python function invoked from C++ throws an exception, it is converted
-into a C++ exception of type :class:`error_already_set` whose string payload
-contains a textual summary.
+When a Python function invoked from C++ throws an exception, pybind11 will convert
+it into a C++ exception of type :class:`error_already_set` whose string payload
+contains a textual summary. If you call the Python C-API directly, and it
+returns an error, you should ``throw py::error_already_set();``, which allows
+pybind11 to deal with the exception and pass it back to the Python interpreter.
+(Another option is to call ``PyErr_Clear`` in the
+`Python C-API <https://docs.python.org/3/c-api/exceptions.html#c.PyErr_Clear>`_
+to clear the error. The Python error must be thrown or cleared, or Python/pybind11
+will be left in an invalid state.)
 
 There is also a special exception :class:`cast_error` that is thrown by
 :func:`handle::call` when the input arguments cannot be converted to Python
@@ -142,3 +148,43 @@
     Exceptions that you do not plan to handle should simply not be caught, or
     may be explicitly (re-)thrown to delegate it to the other,
     previously-declared existing exception translators.
+
+.. _unraisable_exceptions:
+
+Handling unraisable exceptions
+==============================
+
+If a Python function invoked from a C++ destructor or any function marked
+``noexcept(true)`` (collectively, "noexcept functions") throws an exception, there
+is no way to propagate the exception, as such functions may not throw at
+run-time.
+
+Neither Python nor C++ allow exceptions raised in a noexcept function to propagate. In
+Python, an exception raised in a class's ``__del__`` method is logged as an
+unraisable error. In Python 3.8+, a system hook is triggered and an auditing
+event is logged. In C++, ``std::terminate()`` is called to abort immediately.
+
+Any noexcept function should have a try-catch block that traps
+class:`error_already_set` (or any other exception that can occur). Note that pybind11
+wrappers around Python exceptions such as :class:`pybind11::value_error` are *not*
+Python exceptions; they are C++ exceptions that pybind11 catches and converts to
+Python exceptions. Noexcept functions cannot propagate these exceptions either.
+You can convert them to Python exceptions and then discard as unraisable.
+
+.. code-block:: cpp
+
+    void nonthrowing_func() noexcept(true) {
+        try {
+            // ...
+        } catch (py::error_already_set &eas) {
+            // Discard the Python error using Python APIs, using the C++ magic
+            // variable __func__. Python already knows the type and value and of the
+            // exception object.
+            eas.discard_as_unraisable(__func__);
+        } catch (const std::exception &e) {
+            // Log and discard C++ exceptions.
+            // (We cannot use discard_as_unraisable, since we have a generic C++
+            // exception, not an exception that originated from Python.)
+            third_party::log(e);
+        }
+    }