From cd590a7cede156a4244e7cac61e4504e5344d842 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 28 May 2019 00:39:52 +0200 Subject: 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. --- Python/pythonrun.c | 38 ++++++++++++++++++++++++-------------- 1 file changed, 24 insertions(+), 14 deletions(-) (limited to 'Python/pythonrun.c') diff --git a/Python/pythonrun.c b/Python/pythonrun.c index 665c9c9586..ba1d1cf02f 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 * -- cgit v1.2.1