mirror of
https://github.com/python/cpython.git
synced 2025-07-08 03:45:36 +00:00
gh-102755: Add PyErr_DisplayException(exc) (#102756)
This commit is contained in:
parent
405739f916
commit
3f9285a8c5
13 changed files with 76 additions and 78 deletions
|
@ -761,39 +761,34 @@ handle_system_exit(void)
|
|||
static void
|
||||
_PyErr_PrintEx(PyThreadState *tstate, int set_sys_last_vars)
|
||||
{
|
||||
PyObject *exception, *v, *tb, *hook;
|
||||
|
||||
PyObject *typ = NULL, *tb = NULL;
|
||||
handle_system_exit();
|
||||
|
||||
_PyErr_Fetch(tstate, &exception, &v, &tb);
|
||||
if (exception == NULL) {
|
||||
PyObject *exc = _PyErr_GetRaisedException(tstate);
|
||||
if (exc == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
_PyErr_NormalizeException(tstate, &exception, &v, &tb);
|
||||
assert(PyExceptionInstance_Check(exc));
|
||||
typ = Py_NewRef(Py_TYPE(exc));
|
||||
tb = PyException_GetTraceback(exc);
|
||||
if (tb == NULL) {
|
||||
tb = Py_NewRef(Py_None);
|
||||
}
|
||||
PyException_SetTraceback(v, tb);
|
||||
if (exception == NULL) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Now we know v != NULL too */
|
||||
if (set_sys_last_vars) {
|
||||
if (_PySys_SetAttr(&_Py_ID(last_type), exception) < 0) {
|
||||
if (_PySys_SetAttr(&_Py_ID(last_type), typ) < 0) {
|
||||
_PyErr_Clear(tstate);
|
||||
}
|
||||
if (_PySys_SetAttr(&_Py_ID(last_value), v) < 0) {
|
||||
if (_PySys_SetAttr(&_Py_ID(last_value), exc) < 0) {
|
||||
_PyErr_Clear(tstate);
|
||||
}
|
||||
if (_PySys_SetAttr(&_Py_ID(last_traceback), tb) < 0) {
|
||||
_PyErr_Clear(tstate);
|
||||
}
|
||||
}
|
||||
hook = _PySys_GetAttr(tstate, &_Py_ID(excepthook));
|
||||
PyObject *hook = _PySys_GetAttr(tstate, &_Py_ID(excepthook));
|
||||
if (_PySys_Audit(tstate, "sys.excepthook", "OOOO", hook ? hook : Py_None,
|
||||
exception, v, tb) < 0) {
|
||||
typ, exc, tb) < 0) {
|
||||
if (PyErr_ExceptionMatches(PyExc_RuntimeError)) {
|
||||
PyErr_Clear();
|
||||
goto done;
|
||||
|
@ -802,46 +797,34 @@ _PyErr_PrintEx(PyThreadState *tstate, int set_sys_last_vars)
|
|||
}
|
||||
if (hook) {
|
||||
PyObject* stack[3];
|
||||
PyObject *result;
|
||||
|
||||
stack[0] = exception;
|
||||
stack[1] = v;
|
||||
stack[0] = typ;
|
||||
stack[1] = exc;
|
||||
stack[2] = tb;
|
||||
result = _PyObject_FastCall(hook, stack, 3);
|
||||
PyObject *result = _PyObject_FastCall(hook, stack, 3);
|
||||
if (result == NULL) {
|
||||
handle_system_exit();
|
||||
|
||||
PyObject *exception2, *v2, *tb2;
|
||||
_PyErr_Fetch(tstate, &exception2, &v2, &tb2);
|
||||
_PyErr_NormalizeException(tstate, &exception2, &v2, &tb2);
|
||||
/* It should not be possible for exception2 or v2
|
||||
to be NULL. However PyErr_Display() can't
|
||||
tolerate NULLs, so just be safe. */
|
||||
if (exception2 == NULL) {
|
||||
exception2 = Py_NewRef(Py_None);
|
||||
}
|
||||
if (v2 == NULL) {
|
||||
v2 = Py_NewRef(Py_None);
|
||||
}
|
||||
PyObject *exc2 = _PyErr_GetRaisedException(tstate);
|
||||
assert(exc2 && PyExceptionInstance_Check(exc2));
|
||||
fflush(stdout);
|
||||
PySys_WriteStderr("Error in sys.excepthook:\n");
|
||||
PyErr_Display(exception2, v2, tb2);
|
||||
PyErr_DisplayException(exc2);
|
||||
PySys_WriteStderr("\nOriginal exception was:\n");
|
||||
PyErr_Display(exception, v, tb);
|
||||
Py_DECREF(exception2);
|
||||
Py_DECREF(v2);
|
||||
Py_XDECREF(tb2);
|
||||
PyErr_DisplayException(exc);
|
||||
Py_DECREF(exc2);
|
||||
}
|
||||
else {
|
||||
Py_DECREF(result);
|
||||
}
|
||||
Py_XDECREF(result);
|
||||
}
|
||||
else {
|
||||
PySys_WriteStderr("sys.excepthook is missing\n");
|
||||
PyErr_Display(exception, v, tb);
|
||||
PyErr_DisplayException(exc);
|
||||
}
|
||||
|
||||
done:
|
||||
Py_XDECREF(exception);
|
||||
Py_XDECREF(v);
|
||||
Py_XDECREF(typ);
|
||||
Py_XDECREF(exc);
|
||||
Py_XDECREF(tb);
|
||||
}
|
||||
|
||||
|
@ -1505,7 +1488,7 @@ error:
|
|||
#define PyErr_MAX_GROUP_DEPTH 10
|
||||
|
||||
void
|
||||
_PyErr_Display(PyObject *file, PyObject *exception, PyObject *value, PyObject *tb)
|
||||
_PyErr_Display(PyObject *file, PyObject *unused, PyObject *value, PyObject *tb)
|
||||
{
|
||||
assert(file != NULL && file != Py_None);
|
||||
if (PyExceptionInstance_Check(value)
|
||||
|
@ -1513,10 +1496,12 @@ _PyErr_Display(PyObject *file, PyObject *exception, PyObject *value, PyObject *t
|
|||
/* Put the traceback on the exception, otherwise it won't get
|
||||
displayed. See issue #18776. */
|
||||
PyObject *cur_tb = PyException_GetTraceback(value);
|
||||
if (cur_tb == NULL)
|
||||
if (cur_tb == NULL) {
|
||||
PyException_SetTraceback(value, tb);
|
||||
else
|
||||
}
|
||||
else {
|
||||
Py_DECREF(cur_tb);
|
||||
}
|
||||
}
|
||||
|
||||
struct exception_print_context ctx;
|
||||
|
@ -1552,7 +1537,7 @@ _PyErr_Display(PyObject *file, PyObject *exception, PyObject *value, PyObject *t
|
|||
}
|
||||
|
||||
void
|
||||
PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
|
||||
PyErr_Display(PyObject *unused, PyObject *value, PyObject *tb)
|
||||
{
|
||||
PyThreadState *tstate = _PyThreadState_GET();
|
||||
PyObject *file = _PySys_GetAttr(tstate, &_Py_ID(stderr));
|
||||
|
@ -1565,10 +1550,20 @@ PyErr_Display(PyObject *exception, PyObject *value, PyObject *tb)
|
|||
return;
|
||||
}
|
||||
Py_INCREF(file);
|
||||
_PyErr_Display(file, exception, value, tb);
|
||||
_PyErr_Display(file, NULL, value, tb);
|
||||
Py_DECREF(file);
|
||||
}
|
||||
|
||||
void _PyErr_DisplayException(PyObject *file, PyObject *exc)
|
||||
{
|
||||
_PyErr_Display(file, NULL, exc, NULL);
|
||||
}
|
||||
|
||||
void PyErr_DisplayException(PyObject *exc)
|
||||
{
|
||||
PyErr_Display(NULL, exc, NULL);
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PyRun_StringFlags(const char *str, int start, PyObject *globals,
|
||||
PyObject *locals, PyCompilerFlags *flags)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue