summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@redhat.com>2019-05-27 22:39:52 (GMT)
committerGitHub <noreply@github.com>2019-05-27 22:39:52 (GMT)
commitcd590a7cede156a4244e7cac61e4504e5344d842 (patch)
tree371aa076f7be6e942e904ebfa6aa6e7dbb2f0678 /Python
parent23b4b697e5b6cc897696f9c0288c187d2d24bff2 (diff)
downloadcpython-cd590a7cede156a4244e7cac61e4504e5344d842.zip
cpython-cd590a7cede156a4244e7cac61e4504e5344d842.tar.gz
cpython-cd590a7cede156a4244e7cac61e4504e5344d842.tar.bz2
bpo-1230540: Add threading.excepthook() (GH-13515)
Add a new threading.excepthook() function which handles uncaught Thread.run() exception. It can be overridden to control how uncaught exceptions are handled. threading.ExceptHookArgs is not documented on purpose: it should not be used directly. * threading.excepthook() and threading.ExceptHookArgs. * Add _PyErr_Display(): similar to PyErr_Display(), but accept a 'file' parameter. * Add _thread._excepthook(): C implementation of the exception hook calling _PyErr_Display(). * Add _thread._ExceptHookArgs: structseq type. * Add threading._invoke_excepthook_wrapper() which handles the gory details to ensure that everything remains alive during Python shutdown. * Add unit tests.
Diffstat (limited to 'Python')
-rw-r--r--Python/pythonrun.c38
1 files changed, 24 insertions, 14 deletions
diff --git a/Python/pythonrun.c b/Python/pythonrun.c
index 665c9c9..ba1d1cf 100644
--- a/Python/pythonrun.c
+++ b/Python/pythonrun.c
@@ -953,10 +953,11 @@ print_exception_recursive(PyObject *f, PyObject *value, PyObject *seen)
}
void
-PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
+_PyErr_Display(PyObject *file, PyObject *exception, PyObject *value, PyObject *tb)
{
+ assert(file != NULL && file != Py_None);
+
PyObject *seen;
- PyObject *f = _PySys_GetObjectId(&PyId_stderr);
if (PyExceptionInstance_Check(value)
&& tb != NULL && PyTraceBack_Check(tb)) {
/* Put the traceback on the exception, otherwise it won't get
@@ -967,23 +968,32 @@ PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
else
Py_DECREF(cur_tb);
}
- if (f == Py_None) {
- /* pass */
+
+ /* We choose to ignore seen being possibly NULL, and report
+ at least the main exception (it could be a MemoryError).
+ */
+ seen = PySet_New(NULL);
+ if (seen == NULL) {
+ PyErr_Clear();
}
- else if (f == NULL) {
+ print_exception_recursive(file, value, seen);
+ Py_XDECREF(seen);
+}
+
+void
+PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
+{
+ PyObject *file = _PySys_GetObjectId(&PyId_stderr);
+ if (file == NULL) {
_PyObject_Dump(value);
fprintf(stderr, "lost sys.stderr\n");
+ return;
}
- else {
- /* We choose to ignore seen being possibly NULL, and report
- at least the main exception (it could be a MemoryError).
- */
- seen = PySet_New(NULL);
- if (seen == NULL)
- PyErr_Clear();
- print_exception_recursive(f, value, seen);
- Py_XDECREF(seen);
+ if (file == Py_None) {
+ return;
}
+
+ _PyErr_Display(file, exception, value, tb);
}
PyObject *