gh-108082: Add PyErr_FormatUnraisable() function (GH-111086)

This commit is contained in:
Serhiy Storchaka 2023-10-31 23:42:44 +02:00 committed by GitHub
parent 453e96e302
commit f6a02327b5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 142 additions and 8 deletions

View file

@ -1569,14 +1569,16 @@ _PyErr_WriteUnraisableDefaultHook(PyObject *args)
for Python to handle it. For example, when a destructor raises an exception
or during garbage collection (gc.collect()).
If err_msg_str is non-NULL, the error message is formatted as:
"Exception ignored %s" % err_msg_str. Otherwise, use "Exception ignored in"
error message.
If format is non-NULL, the error message is formatted using format and
variable arguments as in PyUnicode_FromFormat().
Otherwise, use "Exception ignored in" error message.
An exception must be set when calling this function. */
void
_PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj)
static void
format_unraisable_v(const char *format, va_list va, PyObject *obj)
{
const char *err_msg_str;
PyThreadState *tstate = _PyThreadState_GET();
_Py_EnsureTstateNotNULL(tstate);
@ -1610,8 +1612,8 @@ _PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj)
}
}
if (err_msg_str != NULL) {
err_msg = PyUnicode_FromFormat("Exception ignored %s", err_msg_str);
if (format != NULL) {
err_msg = PyUnicode_FromFormatV(format, va);
if (err_msg == NULL) {
PyErr_Clear();
}
@ -1676,11 +1678,41 @@ done:
_PyErr_Clear(tstate); /* Just in case */
}
void
PyErr_FormatUnraisable(const char *format, ...)
{
va_list va;
va_start(va, format);
format_unraisable_v(format, va, NULL);
va_end(va);
}
static void
format_unraisable(PyObject *obj, const char *format, ...)
{
va_list va;
va_start(va, format);
format_unraisable_v(format, va, obj);
va_end(va);
}
void
_PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj)
{
if (err_msg_str) {
format_unraisable(obj, "Exception ignored %s", err_msg_str);
}
else {
format_unraisable(obj, NULL);
}
}
void
PyErr_WriteUnraisable(PyObject *obj)
{
_PyErr_WriteUnraisableMsg(NULL, obj);
format_unraisable(obj, NULL);
}