mirror of
https://github.com/python/cpython.git
synced 2025-07-09 20:35:26 +00:00
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.
This commit is contained in:
parent
23b4b697e5
commit
cd590a7ced
9 changed files with 424 additions and 67 deletions
|
@ -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 *
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue