8000 GH-101578: Normalize the current exception by markshannon · Pull Request #101607 · python/cpython · GitHub
[go: up one dir, main page]

Skip to content

GH-101578: Normalize the current exception #101607

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Feb 8, 2023
Prev Previous commit
Next Next commit
Replace a some uses of PyErr_Fetch with PyErr_Fetch1.
  • Loading branch information
markshannon committed Feb 6, 2023
commit 8b62323f4575f5147f9a8889f66764b70c52ba05
1 change: 1 addition & 0 deletions Include/cpython/pyerrors.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ PyAPI_FUNC(void) _PyErr_GetExcInfo(PyThreadState *, PyObject **, PyObject **, Py
/* Context manipulation (PEP 3134) */

PyAPI_FUNC(void) _PyErr_ChainExceptions(PyObject *, PyObject *, PyObject *);
PyAPI_FUNC(void) _PyErr_ChainExceptions1(PyObject *);

/* Like PyErr_Format(), but saves current exception as __context__ and
__cause__.
Expand Down
5 changes: 2 additions & 3 deletions Modules/gcmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -2082,11 +2082,10 @@ PyGC_Collect(void)
n = 0;
}
else {
PyObject *exc, *value, *tb;
gcstate->collecting = 1;
_PyErr_Fetch(tstate, &exc, &value, &tb);
PyObject *exc = _PyErr_Fetch1(tstate);
n = gc_collect_with_callback(tstate, NUM_GENERATIONS - 1);
_PyErr_Restore(tstate, exc, value, tb);
_PyErr_Restore1(tstate, exc);
gcstate->collecting = 0;
}

Expand Down
6 changes: 3 additions & 3 deletions Objects/dictobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -1663,15 +1663,15 @@ PyDict_GetItem(PyObject *op, PyObject *key)
#endif

/* Preserve the existing exception */
PyObject *exc_type, *exc_value, *exc_tb;
PyObject *value;
Py_ssize_t ix; (void)ix;

_PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);

PyObject *exc = _PyErr_Fetch1(tstate);
ix = _Py_dict_lookup(mp, key, hash, &value);

/* Ignore any exception raised by the lookup */
_PyErr_Restore(tstate, exc_type, exc_value, exc_tb);
_PyErr_Restore1(tstate, exc);


assert(ix >= 0 || value == NULL);
Expand Down
4 changes: 1 addition & 3 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -787,9 +787,7 @@ dummy_func(
DECREF_INPUTS();
}
else {
PyObject *exc_type = Py_NewRef(Py_TYPE(exc_value));
PyObject *exc_traceback = PyException_GetTraceback(exc_value);
_PyErr_Restore(tstate, exc_type, Py_NewRef(exc_value), exc_traceback);
_PyErr_Restore1(tstate, Py_NewRef(exc_value));
goto exception_unwind;
}
}
Expand Down
22 changes: 22 additions & 0 deletions Python/errors.c
Original file line number Diff line number Diff line change
Expand Up @@ -626,6 +626,28 @@ _PyErr_ChainExceptions(PyObject *typ, PyObject *val, PyObject *tb)
}
}

/* Like PyErr_Restore1(), but if an exception is already set,
set the context associated with it.

The caller is responsible for ensuring that this call won't create
any cycles in the exception context chain. */
void
_PyErr_ChainExceptions1(PyObject *exc)
{
if (exc == NULL) {
return;
}
PyThreadState *tstate = _PyThreadState_GET();
if (_PyErr_Occurred(tstate)) {
PyObject *exc2 = _PyErr_Fetch1(tstate);
PyException_SetContext(exc2, exc);
_PyErr_Restore1(tstate, exc2);
}
else {
_PyErr_Restore1(tstate, exc);
}
}

/* Set the currently set exception's context to the given exception.

If the provided exc_info is NULL, then the current Python thread state's
Expand Down
5 changes: 2 additions & 3 deletions Python/initconfig.c
Original file line number Diff line number Diff line change
Expand Up @@ -3143,8 +3143,7 @@ init_dump_ascii_wstr(const wchar_t *str)
void
_Py_DumpPathConfig(PyThreadState *tstate)
{
PyObject *exc_type, *exc_value, *exc_tb;
_PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);
PyObject *exc = _PyErr_Fetch1(tstate);

PySys_WriteStderr("Python path configuration:\n");

Expand Down Expand Up @@ -3202,5 +3201,5 @@ _Py_DumpPathConfig(PyThreadState *tstate)
PySys_WriteStderr(" ]\n");
}

_PyErr_Restore(tstate, exc_type, exc_value, exc_tb);
_PyErr_Restore1(tstate, exc);
}
10 changes: 4 additions & 6 deletions Python/sysmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,12 +66,11 @@ _PySys_GetAttr(PyThreadState *tstate, PyObject *name)
if (sd == NULL) {
return NULL;
}
PyObject *exc_type, *exc_value, *exc_tb;
_PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb);
PyObject *exc = _PyErr_Fetch1(tstate);
/* XXX Suppress a new exception if it was raised and restore
* the old one. */
PyObject *value = _PyDict_GetItemWithError(sd, name);
_PyErr_Restore(tstate, exc_type, exc_value, exc_tb);
_PyErr_Restore1(tstate, exc);
return value;
}

Expand Down Expand Up @@ -3704,11 +3703,10 @@ static void
sys_format(PyObject *key, FILE *fp, const char *format, va_list va)
{
PyObject *file, *message;
PyObject *error_type, *error_value, *error_traceback;
const char *utf8;
PyThreadState *tstate = _PyThreadState_GET();

_PyErr_Fetch(tstate, &error_type, &error_value, &error_traceback);
PyObject *error = _PyErr_Fetch1(tstate);
file = _PySys_GetAttr(tstate, key);
message = PyUnicode_FromFormatV(format, va);
if (message != NULL) {
Expand All @@ -3720,7 +3718,7 @@ sys_format(PyObject *key, FILE *fp, const char *format, va_list va)
}
Py_DECREF(message);
}
_PyErr_Restore(tstate, error_type, error_value, error_traceback);
_PyErr_Restore1(tstate, error);
}

void
Expand Down
7 changes: 3 additions & 4 deletions Python/traceback.c
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,12 @@ void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
PyObject *globals;
PyCodeObject *code;
PyFrameObject *frame;
PyObject *exc, *val, *tb;
PyThreadState *tstate = _PyThreadState_GET();

/* Save and clear the current exception. Python functions must not be
called with an exception set. Calling Python functions happens when
the codec of the filesystem encoding is implemented in pure Python. */
_PyErr_Fetch(tstate, &exc, &val, &tb);
PyObject *exc = _PyErr_Fetch1(tstate);

globals = PyDict_New();
if (!globals)
Expand All @@ -285,13 +284,13 @@ void _PyTraceback_Add(const char *funcname, const char *filename, int lineno)
goto error;
frame->f_lineno = lineno;

_PyErr_Restore(tstate, exc, val, tb);
_PyErr_Restore1(tstate, exc);
PyTraceBack_Here(frame);
Py_DECREF(frame);
return;

error:
_PyErr_ChainExceptions(exc, val, tb);
_PyErr_ChainExceptions1(exc);
}

static PyObject *
Expand Down
0