diff options
author | Victor Stinner <vstinner@redhat.com> | 2019-05-27 06:57:14 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-05-27 06:57:14 (GMT) |
commit | 71c52e3048dd07567f0c690eab4e5d57be66f534 (patch) | |
tree | 7f3a063d2d3edb324d7d00bf13a66ddad689d22e /Python/errors.c | |
parent | 2f0bfd27a5e3a9a7cbeb2ddd45ce50c3d4bdb4e9 (diff) | |
download | cpython-71c52e3048dd07567f0c690eab4e5d57be66f534.zip cpython-71c52e3048dd07567f0c690eab4e5d57be66f534.tar.gz cpython-71c52e3048dd07567f0c690eab4e5d57be66f534.tar.bz2 |
bpo-36829: Add _PyErr_WriteUnraisableMsg() (GH-13488)
* sys.unraisablehook: add 'err_msg' field to UnraisableHookArgs.
* Use _PyErr_WriteUnraisableMsg() in _ctypes _DictRemover_call()
and gc delete_garbage().
Diffstat (limited to 'Python/errors.c')
-rw-r--r-- | Python/errors.c | 84 |
1 files changed, 71 insertions, 13 deletions
diff --git a/Python/errors.c b/Python/errors.c index e721f19..831f111 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -1077,6 +1077,7 @@ static PyStructSequence_Field UnraisableHookArgs_fields[] = { {"exc_type", "Exception type"}, {"exc_value", "Exception value"}, {"exc_traceback", "Exception traceback"}, + {"err_msg", "Error message"}, {"object", "Object causing the exception"}, {0} }; @@ -1085,7 +1086,7 @@ static PyStructSequence_Desc UnraisableHookArgs_desc = { .name = "UnraisableHookArgs", .doc = UnraisableHookArgs__doc__, .fields = UnraisableHookArgs_fields, - .n_in_sequence = 4 + .n_in_sequence = 5 }; @@ -1104,7 +1105,8 @@ _PyErr_Init(void) static PyObject * make_unraisable_hook_args(PyThreadState *tstate, PyObject *exc_type, - PyObject *exc_value, PyObject *exc_tb, PyObject *obj) + PyObject *exc_value, PyObject *exc_tb, + PyObject *err_msg, PyObject *obj) { PyObject *args = PyStructSequence_New(&UnraisableHookArgsType); if (args == NULL) { @@ -1125,6 +1127,7 @@ make_unraisable_hook_args(PyThreadState *tstate, PyObject *exc_type, ADD_ITEM(exc_type); ADD_ITEM(exc_value); ADD_ITEM(exc_tb); + ADD_ITEM(err_msg); ADD_ITEM(obj); #undef ADD_ITEM @@ -1145,11 +1148,21 @@ make_unraisable_hook_args(PyThreadState *tstate, PyObject *exc_type, static int write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type, PyObject *exc_value, PyObject *exc_tb, - PyObject *obj, PyObject *file) + PyObject *err_msg, PyObject *obj, PyObject *file) { if (obj != NULL && obj != Py_None) { - if (PyFile_WriteString("Exception ignored in: ", file) < 0) { - return -1; + if (err_msg != NULL && err_msg != Py_None) { + if (PyFile_WriteObject(err_msg, file, Py_PRINT_RAW) < 0) { + return -1; + } + if (PyFile_WriteString(": ", file) < 0) { + return -1; + } + } + else { + if (PyFile_WriteString("Exception ignored in: ", file) < 0) { + return -1; + } } if (PyFile_WriteObject(obj, file, 0) < 0) { @@ -1162,6 +1175,14 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type, return -1; } } + else if (err_msg != NULL && err_msg != Py_None) { + if (PyFile_WriteObject(err_msg, file, Py_PRINT_RAW) < 0) { + return -1; + } + if (PyFile_WriteString(":\n", file) < 0) { + return -1; + } + } if (exc_tb != NULL && exc_tb != Py_None) { if (PyTraceBack_Print(exc_tb, file) < 0) { @@ -1178,8 +1199,9 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type, const char *className = PyExceptionClass_Name(exc_type); if (className != NULL) { const char *dot = strrchr(className, '.'); - if (dot != NULL) + if (dot != NULL) { className = dot+1; + } } _Py_IDENTIFIER(__module__); @@ -1238,7 +1260,8 @@ write_unraisable_exc_file(PyThreadState *tstate, PyObject *exc_type, static int write_unraisable_exc(PyThreadState *tstate, PyObject *exc_type, - PyObject *exc_value, PyObject *exc_tb, PyObject *obj) + PyObject *exc_value, PyObject *exc_tb, PyObject *err_msg, + PyObject *obj) { PyObject *file = _PySys_GetObjectId(&PyId_stderr); if (file == NULL || file == Py_None) { @@ -1249,7 +1272,7 @@ write_unraisable_exc(PyThreadState *tstate, PyObject *exc_type, while we use it */ Py_INCREF(file); int res = write_unraisable_exc_file(tstate, exc_type, exc_value, exc_tb, - obj, file); + err_msg, obj, file); Py_DECREF(file); return res; @@ -1272,9 +1295,10 @@ _PyErr_WriteUnraisableDefaultHook(PyObject *args) PyObject *exc_type = PyStructSequence_GET_ITEM(args, 0); PyObject *exc_value = PyStructSequence_GET_ITEM(args, 1); PyObject *exc_tb = PyStructSequence_GET_ITEM(args, 2); - PyObject *obj = PyStructSequence_GET_ITEM(args, 3); + PyObject *err_msg = PyStructSequence_GET_ITEM(args, 3); + PyObject *obj = PyStructSequence_GET_ITEM(args, 4); - if (write_unraisable_exc(tstate, exc_type, exc_value, exc_tb, obj) < 0) { + if (write_unraisable_exc(tstate, exc_type, exc_value, exc_tb, err_msg, obj) < 0) { return NULL; } Py_RETURN_NONE; @@ -1287,13 +1311,18 @@ _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. + An exception must be set when calling this function. */ void -PyErr_WriteUnraisable(PyObject *obj) +_PyErr_WriteUnraisableMsg(const char *err_msg_str, PyObject *obj) { PyThreadState *tstate = _PyThreadState_GET(); assert(tstate != NULL); + PyObject *err_msg = NULL; PyObject *exc_type, *exc_value, *exc_tb; _PyErr_Fetch(tstate, &exc_type, &exc_value, &exc_tb); @@ -1322,13 +1351,20 @@ PyErr_WriteUnraisable(PyObject *obj) } } + if (err_msg_str != NULL) { + err_msg = PyUnicode_FromFormat("Exception ignored %s", err_msg_str); + if (err_msg == NULL) { + PyErr_Clear(); + } + } + _Py_IDENTIFIER(unraisablehook); PyObject *hook = _PySys_GetObjectId(&PyId_unraisablehook); if (hook != NULL && hook != Py_None) { PyObject *hook_args; hook_args = make_unraisable_hook_args(tstate, exc_type, exc_value, - exc_tb, obj); + exc_tb, err_msg, obj); if (hook_args != NULL) { PyObject *args[1] = {hook_args}; PyObject *res = _PyObject_FastCall(hook, args, 1); @@ -1337,6 +1373,18 @@ PyErr_WriteUnraisable(PyObject *obj) Py_DECREF(res); goto done; } + + err_msg_str = "Exception ignored in sys.unraisablehook"; + } + else { + err_msg_str = ("Exception ignored on building " + "sys.unraisablehook arguments"); + } + + Py_XDECREF(err_msg); + err_msg = PyUnicode_FromString(err_msg_str); + if (err_msg == NULL) { + PyErr_Clear(); } /* sys.unraisablehook failed: log its error using default hook */ @@ -1350,15 +1398,25 @@ PyErr_WriteUnraisable(PyObject *obj) default_hook: /* Call the default unraisable hook (ignore failure) */ - (void)write_unraisable_exc(tstate, exc_type, exc_value, exc_tb, obj); + (void)write_unraisable_exc(tstate, exc_type, exc_value, exc_tb, + err_msg, obj); done: Py_XDECREF(exc_type); Py_XDECREF(exc_value); Py_XDECREF(exc_tb); + Py_XDECREF(err_msg); _PyErr_Clear(tstate); /* Just in case */ } + +void +PyErr_WriteUnraisable(PyObject *obj) +{ + _PyErr_WriteUnraisableMsg(NULL, obj); +} + + extern PyObject *PyModule_GetWarningsModule(void); |