diff options
author | Victor Stinner <vstinner@redhat.com> | 2019-05-27 22:39:52 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-27 22:39:52 (GMT) |
commit | cd590a7cede156a4244e7cac61e4504e5344d842 (patch) | |
tree | 371aa076f7be6e942e904ebfa6aa6e7dbb2f0678 /Python | |
parent | 23b4b697e5b6cc897696f9c0288c187d2d24bff2 (diff) | |
download | cpython-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.c | 38 |
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 * |