+void report_lost_exception_v(struct excinfo *exc,
+ const char *why, va_list ap)
+{
+ PyObject *hookfn = 0;
+ PyObject *whyobj = 0;
+ PyObject *obj = 0;
+
+ /* Make sure we start out without a pending exception, or this will get
+ * really confusing.
+ */
+ assert(!PyErr_Occurred());
+
+ /* Format the explanation. */
+ if (why) whyobj = PyString_FromFormatV(why, ap);
+ else { whyobj = Py_None; Py_INCREF(whyobj); }
+
+ /* Find our home module's `lostexchook' function. This won't work if
+ * there's no module, or the function isn't defined, or it's `None'.
+ */
+ if (!home_module) goto sys;
+ hookfn = PyObject_GetAttrString(home_module, "lostexchook");
+ if (hookfn == Py_None) goto sys;
+ else if (hookfn) ;
+ else if (!PyErr_ExceptionMatches(PyExc_AttributeError)) goto ouch;
+ else { PyErr_Clear(); goto sys; }
+
+ /* Call the hook function. */
+ obj = PyObject_CallFunction(hookfn, "(OOOO)",
+ whyobj, exc->ty, exc->val, exc->tb);
+ if (!obj) goto ouch;
+ goto end;
+
+ /* Something went wrong reporting the problem. */
+ouch:
+ PySys_WriteStderr("\n!!! FAILURE REPORTING LOST EXCEPTION\n");
+ PyErr_Print();
+ /* drop through... */
+
+ /* There was no hook, so try to do something sensible using
+ * `sys.excepthook'.
+ */
+sys:
+ PySys_WriteStderr("\n!!! LOST EXCEPTION: %s\n",
+ PyString_AS_STRING(whyobj));
+ RESTORE_EXCINFO(exc);
+ PyErr_Print();
+ /* drop through... */
+
+ /* Clean up afterwards. */
+end:
+ Py_XDECREF(hookfn);
+ Py_XDECREF(whyobj);
+ Py_XDECREF(obj);
+}
+
+void report_lost_exception(struct excinfo *exc, const char *why, ...)
+{
+ va_list ap;
+
+ va_start(ap, why);
+ report_lost_exception_v(exc, why, ap);
+ va_end(ap);
+}
+
+void stash_exception(struct excinfo *exc, const char *why, ...)
+{
+ va_list ap;
+ struct excinfo stash;
+
+ if (!exc->ty)
+ STASH_EXCINFO(exc);
+ else {
+ va_start(ap, why);
+ STASH_EXCINFO(&stash);
+ report_lost_exception_v(&stash, why, ap);
+ va_end(ap);
+ }
+}
+
+void restore_exception(struct excinfo *exc, const char *why, ...)
+{
+ va_list ap;
+ struct excinfo stash;
+
+ if (!PyErr_Occurred())
+ RESTORE_EXCINFO(exc);
+ else {
+ va_start(ap, why);
+ STASH_EXCINFO(&stash);
+ report_lost_exception_v(exc, why, ap);
+ RESTORE_EXCINFO(&stash);
+ va_end(ap);
+ }
+}
+