diff options
-rw-r--r-- | Doc/c-api/exceptions.rst | 5 | ||||
-rw-r--r-- | Doc/library/sys.rst | 33 | ||||
-rw-r--r-- | Doc/whatsnew/3.8.rst | 10 | ||||
-rw-r--r-- | Include/internal/pycore_pylifecycle.h | 4 | ||||
-rw-r--r-- | Lib/test/test_sys.py | 80 | ||||
-rw-r--r-- | Misc/NEWS.d/next/Library/2019-05-08-12-51-37.bpo-36829.8enFMA.rst | 5 | ||||
-rw-r--r-- | Modules/_testcapimodule.c | 15 | ||||
-rw-r--r-- | Python/clinic/sysmodule.c.h | 18 | ||||
-rw-r--r-- | Python/errors.c | 278 | ||||
-rw-r--r-- | Python/importlib.h | 120 | ||||
-rw-r--r-- | Python/pylifecycle.c | 12 | ||||
-rw-r--r-- | Python/sysmodule.c | 28 |
12 files changed, 491 insertions, 117 deletions
diff --git a/Doc/c-api/exceptions.rst b/Doc/c-api/exceptions.rst index 00ef005..18ff697 100644 --- a/Doc/c-api/exceptions.rst +++ b/Doc/c-api/exceptions.rst @@ -72,6 +72,9 @@ Printing and clearing .. c:function:: void PyErr_WriteUnraisable(PyObject *obj) + Call :func:`sys.unraisablehook` using the current exception and *obj* + argument. + This utility function prints a warning message to ``sys.stderr`` when an exception has been set but it is impossible for the interpreter to actually raise the exception. It is used, for example, when an exception occurs in an @@ -81,6 +84,8 @@ Printing and clearing in which the unraisable exception occurred. If possible, the repr of *obj* will be printed in the warning message. + An exception must be set when calling this function. + Raising exceptions ================== diff --git a/Doc/library/sys.rst b/Doc/library/sys.rst index 7d27c89..3b754bd 100644 --- a/Doc/library/sys.rst +++ b/Doc/library/sys.rst @@ -248,16 +248,19 @@ always available. before the program exits. The handling of such top-level exceptions can be customized by assigning another three-argument function to ``sys.excepthook``. + See also :func:`unraisablehook` which handles unraisable exceptions. + .. data:: __breakpointhook__ __displayhook__ __excepthook__ + __unraisablehook__ These objects contain the original values of ``breakpointhook``, - ``displayhook``, and ``excepthook`` at the start of the program. They are - saved so that ``breakpointhook``, ``displayhook`` and ``excepthook`` can be - restored in case they happen to get replaced with broken or alternative - objects. + ``displayhook``, ``excepthook``, and ``unraisablehook`` at the start of the + program. They are saved so that ``breakpointhook``, ``displayhook`` and + ``excepthook``, ``unraisablehook`` can be restored in case they happen to + get replaced with broken or alternative objects. .. versionadded:: 3.7 __breakpointhook__ @@ -1487,6 +1490,28 @@ always available. is suppressed and only the exception type and value are printed. +.. function:: unraisablehook(unraisable, /) + + Handle an unraisable exception. + + Called when an exception has occurred but there is no way for Python to + handle it. For example, when a destructor raises an exception or during + garbage collection (:func:`gc.collect`). + + The *unraisable* argument has the following attributes: + + * *exc_type*: Exception type. + * *exc_value*: Exception value, can be ``None``. + * *exc_traceback*: Exception traceback, can be ``None``. + * *object*: Object causing the exception, can be ``None``. + + :func:`sys.unraisablehook` can be overridden to control how unraisable + exceptions are handled. + + See also :func:`excepthook` which handles uncaught exceptions. + + .. versionadded:: 3.8 + .. data:: version A string containing the version number of the Python interpreter plus additional diff --git a/Doc/whatsnew/3.8.rst b/Doc/whatsnew/3.8.rst index 5f8208d..63b8200 100644 --- a/Doc/whatsnew/3.8.rst +++ b/Doc/whatsnew/3.8.rst @@ -481,6 +481,16 @@ and manipulating normal distributions of a random variable. [7.672102882379219, 12.000027119750287, 4.647488369766392] +sys +--- + +Add new :func:`sys.unraisablehook` function which can be overridden to control +how "unraisable exceptions" are handled. It is called when an exception has +occurred but there is no way for Python to handle it. For example, when a +destructor raises an exception or during garbage collection +(:func:`gc.collect`). + + tarfile ------- diff --git a/Include/internal/pycore_pylifecycle.h b/Include/internal/pycore_pylifecycle.h index 4684ebe..07cf815 100644 --- a/Include/internal/pycore_pylifecycle.h +++ b/Include/internal/pycore_pylifecycle.h @@ -48,6 +48,7 @@ extern int _PySys_InitMain( PyInterpreterState *interp); extern _PyInitError _PyImport_Init(PyInterpreterState *interp); extern _PyInitError _PyExc_Init(void); +extern _PyInitError _PyErr_Init(void); extern _PyInitError _PyBuiltins_AddExceptions(PyObject * bltinmod); extern _PyInitError _PyImportHooks_Init(void); extern int _PyFloat_Init(void); @@ -100,8 +101,11 @@ PyAPI_FUNC(_PyInitError) _Py_PreInitializeFromCoreConfig( const _PyCoreConfig *coreconfig, const _PyArgv *args); + PyAPI_FUNC(int) _Py_HandleSystemExit(int *exitcode_p); +PyAPI_FUNC(PyObject*) _PyErr_WriteUnraisableDefaultHook(PyObject *unraisable); + #ifdef __cplusplus } #endif diff --git a/Lib/test/test_sys.py b/Lib/test/test_sys.py index d1c7daa..2b358ca 100644 --- a/Lib/test/test_sys.py +++ b/Lib/test/test_sys.py @@ -877,6 +877,81 @@ class SysModuleTest(unittest.TestCase): @test.support.cpython_only +class UnraisableHookTest(unittest.TestCase): + def write_unraisable_exc(self, exc, obj): + import _testcapi + import types + try: + # raise the exception to get a traceback in the except block + try: + raise exc + except Exception as exc2: + _testcapi.write_unraisable_exc(exc2, obj) + return types.SimpleNamespace(exc_type=type(exc2), + exc_value=exc2, + exc_traceback=exc2.__traceback__, + object=obj) + finally: + # Explicitly break any reference cycle + exc = None + exc2 = None + + def test_original_unraisablehook(self): + obj = "an object" + + with test.support.captured_output("stderr") as stderr: + with test.support.swap_attr(sys, 'unraisablehook', + sys.__unraisablehook__): + self.write_unraisable_exc(ValueError(42), obj) + + err = stderr.getvalue() + self.assertIn(f'Exception ignored in: {obj!r}\n', err) + self.assertIn('Traceback (most recent call last):\n', err) + self.assertIn('ValueError: 42\n', err) + + def test_original_unraisablehook_wrong_type(self): + exc = ValueError(42) + with test.support.swap_attr(sys, 'unraisablehook', + sys.__unraisablehook__): + with self.assertRaises(TypeError): + sys.unraisablehook(exc) + + def test_custom_unraisablehook(self): + hook_args = None + + def hook_func(args): + nonlocal hook_args + hook_args = args + + obj = object() + try: + with test.support.swap_attr(sys, 'unraisablehook', hook_func): + expected = self.write_unraisable_exc(ValueError(42), obj) + for attr in "exc_type exc_value exc_traceback object".split(): + self.assertEqual(getattr(hook_args, attr), + getattr(expected, attr), + (hook_args, expected)) + finally: + # expected and hook_args contain an exception: break reference cycle + expected = None + hook_args = None + + def test_custom_unraisablehook_fail(self): + def hook_func(*args): + raise Exception("hook_func failed") + + with test.support.captured_output("stderr") as stderr: + with test.support.swap_attr(sys, 'unraisablehook', hook_func): + self.write_unraisable_exc(ValueError(42), None) + + err = stderr.getvalue() + self.assertIn(f'Exception ignored in: {hook_func!r}\n', + err) + self.assertIn('Traceback (most recent call last):\n', err) + self.assertIn('Exception: hook_func failed\n', err) + + +@test.support.cpython_only class SizeofTest(unittest.TestCase): def setUp(self): @@ -1277,8 +1352,5 @@ class SizeofTest(unittest.TestCase): self.assertIsNone(cur.finalizer) -def test_main(): - test.support.run_unittest(SysModuleTest, SizeofTest) - if __name__ == "__main__": - test_main() + unittest.main() diff --git a/Misc/NEWS.d/next/Library/2019-05-08-12-51-37.bpo-36829.8enFMA.rst b/Misc/NEWS.d/next/Library/2019-05-08-12-51-37.bpo-36829.8enFMA.rst new file mode 100644 index 0000000..0b04efc --- /dev/null +++ b/Misc/NEWS.d/next/Library/2019-05-08-12-51-37.bpo-36829.8enFMA.rst @@ -0,0 +1,5 @@ +Add new :func:`sys.unraisablehook` function which can be overridden to +control how "unraisable exceptions" are handled. It is called when an +exception has occurred but there is no way for Python to handle it. For +example, when a destructor raises an exception or during garbage collection +(:func:`gc.collect`). diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c index 2af5539..7945f49 100644 --- a/Modules/_testcapimodule.c +++ b/Modules/_testcapimodule.c @@ -4982,6 +4982,20 @@ negative_refcount(PyObject *self, PyObject *Py_UNUSED(args)) #endif +static PyObject* +test_write_unraisable_exc(PyObject *self, PyObject *args) +{ + PyObject *exc, *obj; + if (!PyArg_ParseTuple(args, "OO", &exc, &obj)) { + return NULL; + } + + PyErr_SetObject((PyObject *)Py_TYPE(exc), exc); + PyErr_WriteUnraisable(obj); + Py_RETURN_NONE; +} + + static PyMethodDef TestMethods[] = { {"raise_exception", raise_exception, METH_VARARGS}, {"raise_memoryerror", raise_memoryerror, METH_NOARGS}, @@ -5221,6 +5235,7 @@ static PyMethodDef TestMethods[] = { #ifdef Py_REF_DEBUG {"negative_refcount", negative_refcount, METH_NOARGS}, #endif + {"write_unraisable_exc", test_write_unraisable_exc, METH_VARARGS}, {NULL, NULL} /* sentinel */ }; diff --git a/Python/clinic/sysmodule.c.h b/Python/clinic/sysmodule.c.h index c70b721..aede60a 100644 --- a/Python/clinic/sysmodule.c.h +++ b/Python/clinic/sysmodule.c.h @@ -65,6 +65,22 @@ sys_exc_info(PyObject *module, PyObject *Py_UNUSED(ignored)) return sys_exc_info_impl(module); } +PyDoc_STRVAR(sys_unraisablehook__doc__, +"unraisablehook($module, unraisable, /)\n" +"--\n" +"\n" +"Handle an unraisable exception.\n" +"\n" +"The unraisable argument has the following attributes:\n" +"\n" +"* exc_type: Exception type.\n" +"* exc_value: Exception value.\n" +"* exc_tb: Exception traceback, can be None.\n" +"* obj: Object causing the exception, can be None."); + +#define SYS_UNRAISABLEHOOK_METHODDEF \ + {"unraisablehook", (PyCFunction)sys_unraisablehook, METH_O, sys_unraisablehook__doc__}, + PyDoc_STRVAR(sys_exit__doc__, "exit($module, status=None, /)\n" "--\n" @@ -1060,4 +1076,4 @@ sys_getandroidapilevel(PyObject *module, PyObject *Py_UNUSED(ignored)) #ifndef SYS_GETANDROIDAPILEVEL_METHODDEF #define SYS_GETANDROIDAPILEVEL_METHODDEF #endif /* !defined(SYS_GETANDROIDAPILEVEL_METHODDEF) */ -/*[clinic end generated code: output=3ba4c194d00f1866 input=a9049054013a1b77]*/ +/*[clinic end generated code: output=603e4d5a453dc769 input=a9049054013a1b77]*/ diff --git a/Python/errors.c b/Python/errors.c index b8af1df..9622b5a 100644 --- a/Python/errors.c +++ b/Python/errors.c @@ -2,6 +2,7 @@ /* Error handling */ #include "Python.h" +#include "pycore_coreconfig.h" #include "pycore_pystate.h" #ifndef __STDC__ @@ -944,90 +945,271 @@ PyErr_NewExceptionWithDoc(const char *name, const char *doc, } -/* Call when an exception has occurred but there is no way for Python - to handle it. Examples: exception in __del__ or during GC. */ -void -PyErr_WriteUnraisable(PyObject *obj) +PyDoc_STRVAR(UnraisableHookArgs__doc__, +"UnraisableHookArgs\n\ +\n\ +Type used to pass arguments to sys.unraisablehook."); + +static PyTypeObject UnraisableHookArgsType; + +static PyStructSequence_Field UnraisableHookArgs_fields[] = { + {"exc_type", "Exception type"}, + {"exc_value", "Exception value"}, + {"exc_traceback", "Exception traceback"}, + {"object", "Object causing the exception"}, + {0} +}; + +static PyStructSequence_Desc UnraisableHookArgs_desc = { + .name = "UnraisableHookArgs", + .doc = UnraisableHookArgs__doc__, + .fields = UnraisableHookArgs_fields, + .n_in_sequence = 4 +}; + + +_PyInitError +_PyErr_Init(void) { - _Py_IDENTIFIER(__module__); - PyObject *f, *t, *v, *tb; - PyObject *moduleName = NULL; - const char *className; + if (UnraisableHookArgsType.tp_name == NULL) { + if (PyStructSequence_InitType2(&UnraisableHookArgsType, + &UnraisableHookArgs_desc) < 0) { + return _Py_INIT_ERR("failed to initialize UnraisableHookArgs type"); + } + } + return _Py_INIT_OK(); +} - PyErr_Fetch(&t, &v, &tb); - f = _PySys_GetObjectId(&PyId_stderr); - if (f == NULL || f == Py_None) - goto done; +static PyObject * +make_unraisable_hook_args(PyObject *exc_type, PyObject *exc_value, + PyObject *exc_tb, PyObject *obj) +{ + PyObject *args = PyStructSequence_New(&UnraisableHookArgsType); + if (args == NULL) { + return NULL; + } + + Py_ssize_t pos = 0; +#define ADD_ITEM(exc_type) \ + do { \ + if (exc_type == NULL) { \ + exc_type = Py_None; \ + } \ + Py_INCREF(exc_type); \ + PyStructSequence_SET_ITEM(args, pos++, exc_type); \ + } while (0) + + + ADD_ITEM(exc_type); + ADD_ITEM(exc_value); + ADD_ITEM(exc_tb); + ADD_ITEM(obj); +#undef ADD_ITEM + + if (PyErr_Occurred()) { + Py_DECREF(args); + return NULL; + } + return args; +} + + + +/* Default implementation of sys.unraisablehook. + + It can be called to log the exception of a custom sys.unraisablehook. - if (obj) { - if (PyFile_WriteString("Exception ignored in: ", f) < 0) - goto done; - if (PyFile_WriteObject(obj, f, 0) < 0) { + Do nothing if sys.stderr attribute doesn't exist or is set to None. */ +static int +write_unraisable_exc_file(PyObject *exc_type, PyObject *exc_value, + PyObject *exc_tb, PyObject *obj, PyObject *file) +{ + if (obj != NULL && obj != Py_None) { + if (PyFile_WriteString("Exception ignored in: ", file) < 0) { + return -1; + } + + if (PyFile_WriteObject(obj, file, 0) < 0) { PyErr_Clear(); - if (PyFile_WriteString("<object repr() failed>", f) < 0) { - goto done; + if (PyFile_WriteString("<object repr() failed>", file) < 0) { + return -1; } } - if (PyFile_WriteString("\n", f) < 0) - goto done; + if (PyFile_WriteString("\n", file) < 0) { + return -1; + } } - if (PyTraceBack_Print(tb, f) < 0) - goto done; + if (exc_tb != NULL && exc_tb != Py_None) { + if (PyTraceBack_Print(exc_tb, file) < 0) { + /* continue even if writing the traceback failed */ + PyErr_Clear(); + } + } - if (!t) - goto done; + if (!exc_type) { + return -1; + } - assert(PyExceptionClass_Check(t)); - className = PyExceptionClass_Name(t); + assert(PyExceptionClass_Check(exc_type)); + const char *className = PyExceptionClass_Name(exc_type); if (className != NULL) { const char *dot = strrchr(className, '.'); if (dot != NULL) className = dot+1; } - moduleName = _PyObject_GetAttrId(t, &PyId___module__); + _Py_IDENTIFIER(__module__); + PyObject *moduleName = _PyObject_GetAttrId(exc_type, &PyId___module__); if (moduleName == NULL || !PyUnicode_Check(moduleName)) { + Py_XDECREF(moduleName); PyErr_Clear(); - if (PyFile_WriteString("<unknown>", f) < 0) - goto done; + if (PyFile_WriteString("<unknown>", file) < 0) { + return -1; + } } else { if (!_PyUnicode_EqualToASCIIId(moduleName, &PyId_builtins)) { - if (PyFile_WriteObject(moduleName, f, Py_PRINT_RAW) < 0) - goto done; - if (PyFile_WriteString(".", f) < 0) - goto done; + if (PyFile_WriteObject(moduleName, file, Py_PRINT_RAW) < 0) { + Py_DECREF(moduleName); + return -1; + } + Py_DECREF(moduleName); + if (PyFile_WriteString(".", file) < 0) { + return -1; + } + } + else { + Py_DECREF(moduleName); } } if (className == NULL) { - if (PyFile_WriteString("<unknown>", f) < 0) - goto done; + if (PyFile_WriteString("<unknown>", file) < 0) { + return -1; + } } else { - if (PyFile_WriteString(className, f) < 0) - goto done; + if (PyFile_WriteString(className, file) < 0) { + return -1; + } } - if (v && v != Py_None) { - if (PyFile_WriteString(": ", f) < 0) - goto done; - if (PyFile_WriteObject(v, f, Py_PRINT_RAW) < 0) { + if (exc_value && exc_value != Py_None) { + if (PyFile_WriteString(": ", file) < 0) { + return -1; + } + if (PyFile_WriteObject(exc_value, file, Py_PRINT_RAW) < 0) { PyErr_Clear(); - if (PyFile_WriteString("<exception str() failed>", f) < 0) { + if (PyFile_WriteString("<exception str() failed>", file) < 0) { + return -1; + } + } + } + if (PyFile_WriteString("\n", file) < 0) { + return -1; + } + return 0; +} + + +static int +write_unraisable_exc(PyObject *exc_type, PyObject *exc_value, + PyObject *exc_tb, PyObject *obj) +{ + PyObject *file = _PySys_GetObjectId(&PyId_stderr); + if (file == NULL || file == Py_None) { + return 0; + } + + /* Hold a strong reference to ensure that sys.stderr doesn't go away + while we use it */ + Py_INCREF(file); + int res = write_unraisable_exc_file(exc_type, exc_value, exc_tb, + obj, file); + Py_DECREF(file); + + return res; +} + + +PyObject* +_PyErr_WriteUnraisableDefaultHook(PyObject *args) +{ + if (Py_TYPE(args) != &UnraisableHookArgsType) { + PyErr_SetString(PyExc_TypeError, + "sys.unraisablehook argument type " + "must be UnraisableHookArgs"); + return NULL; + } + + /* Borrowed references */ + 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); + + if (write_unraisable_exc(exc_type, exc_value, exc_tb, obj) < 0) { + return NULL; + } + Py_RETURN_NONE; +} + + +/* Call sys.unraisablehook(). + + This function can be used when an exception has occurred but there is no way + for Python to handle it. For example, when a destructor raises an exception + or during garbage collection (gc.collect()). + + An exception must be set when calling this function. */ +void +PyErr_WriteUnraisable(PyObject *obj) +{ + PyObject *exc_type, *exc_value, *exc_tb; + + PyErr_Fetch(&exc_type, &exc_value, &exc_tb); + + assert(exc_type != NULL); + + if (exc_type == NULL) { + /* sys.unraisablehook requires that at least exc_type is set */ + goto default_hook; + } + + _Py_IDENTIFIER(unraisablehook); + PyObject *hook = _PySys_GetObjectId(&PyId_unraisablehook); + if (hook != NULL && hook != Py_None) { + PyObject *hook_args; + + hook_args = make_unraisable_hook_args(exc_type, exc_value, exc_tb, obj); + if (hook_args != NULL) { + PyObject *args[1] = {hook_args}; + PyObject *res = _PyObject_FastCall(hook, args, 1); + Py_DECREF(hook_args); + if (res != NULL) { + Py_DECREF(res); goto done; } } + + /* sys.unraisablehook failed: log its error using default hook */ + Py_XDECREF(exc_type); + Py_XDECREF(exc_value); + Py_XDECREF(exc_tb); + PyErr_Fetch(&exc_type, &exc_value, &exc_tb); + + obj = hook; } - if (PyFile_WriteString("\n", f) < 0) - goto done; + +default_hook: + /* Call the default unraisable hook (ignore failure) */ + (void)write_unraisable_exc(exc_type, exc_value, exc_tb, obj); done: - Py_XDECREF(moduleName); - Py_XDECREF(t); - Py_XDECREF(v); - Py_XDECREF(tb); + Py_XDECREF(exc_type); + Py_XDECREF(exc_value); + Py_XDECREF(exc_tb); PyErr_Clear(); /* Just in case */ } diff --git a/Python/importlib.h b/Python/importlib.h index 694984a..5bd1d17 100644 --- a/Python/importlib.h +++ b/Python/importlib.h @@ -1326,8 +1326,8 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 97,114,100,108,101,115,115,32,111,102,32,97,110,121,32,114, 97,105,115,101,100,32,101,120,99,101,112,116,105,111,110,115, 46,78,41,2,114,57,0,0,0,114,60,0,0,0,41,4, - 114,30,0,0,0,90,8,101,120,99,95,116,121,112,101,90, - 9,101,120,99,95,118,97,108,117,101,90,13,101,120,99,95, + 114,30,0,0,0,218,8,101,120,99,95,116,121,112,101,218, + 9,101,120,99,95,118,97,108,117,101,218,13,101,120,99,95, 116,114,97,99,101,98,97,99,107,114,10,0,0,0,114,10, 0,0,0,114,11,0,0,0,114,56,0,0,0,99,3,0, 0,115,2,0,0,0,0,2,122,27,95,73,109,112,111,114, @@ -1358,7 +1358,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 98,97,115,101,114,10,0,0,0,114,10,0,0,0,114,11, 0,0,0,218,13,95,114,101,115,111,108,118,101,95,110,97, 109,101,104,3,0,0,115,10,0,0,0,0,2,16,1,12, - 1,8,1,8,1,114,185,0,0,0,99,3,0,0,0,0, + 1,8,1,8,1,114,188,0,0,0,99,3,0,0,0,0, 0,0,0,0,0,0,0,4,0,0,0,4,0,0,0,67, 0,0,0,115,34,0,0,0,124,0,160,0,124,1,124,2, 161,2,125,3,124,3,100,0,107,8,114,24,100,0,83,0, @@ -1368,7 +1368,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 109,0,0,0,114,10,0,0,0,114,10,0,0,0,114,11, 0,0,0,218,17,95,102,105,110,100,95,115,112,101,99,95, 108,101,103,97,99,121,113,3,0,0,115,8,0,0,0,0, - 3,12,1,8,1,4,1,114,187,0,0,0,99,3,0,0, + 3,12,1,8,1,4,1,114,190,0,0,0,99,3,0,0, 0,0,0,0,0,0,0,0,0,10,0,0,0,10,0,0, 0,67,0,0,0,115,12,1,0,0,116,0,106,1,125,3, 124,3,100,1,107,8,114,22,116,2,100,2,131,1,130,1, @@ -1398,17 +1398,17 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 104,114,79,0,0,0,218,9,95,119,97,114,110,105,110,103, 115,218,4,119,97,114,110,218,13,73,109,112,111,114,116,87, 97,114,110,105,110,103,114,92,0,0,0,114,178,0,0,0, - 114,166,0,0,0,114,106,0,0,0,114,187,0,0,0,114, + 114,166,0,0,0,114,106,0,0,0,114,190,0,0,0,114, 105,0,0,0,41,10,114,17,0,0,0,114,164,0,0,0, - 114,165,0,0,0,114,188,0,0,0,90,9,105,115,95,114, - 101,108,111,97,100,114,186,0,0,0,114,166,0,0,0,114, + 114,165,0,0,0,114,191,0,0,0,90,9,105,115,95,114, + 101,108,111,97,100,114,189,0,0,0,114,166,0,0,0,114, 95,0,0,0,114,96,0,0,0,114,105,0,0,0,114,10, 0,0,0,114,10,0,0,0,114,11,0,0,0,218,10,95, 102,105,110,100,95,115,112,101,99,122,3,0,0,115,54,0, 0,0,0,2,6,1,8,2,8,3,4,1,12,5,10,1, 8,1,8,1,2,1,10,1,14,1,12,1,8,1,20,2, 22,1,8,2,18,1,10,1,2,1,10,1,14,4,14,2, - 8,1,8,2,10,2,10,2,114,192,0,0,0,99,3,0, + 8,1,8,2,10,2,10,2,114,195,0,0,0,99,3,0, 0,0,0,0,0,0,0,0,0,0,3,0,0,0,5,0, 0,0,67,0,0,0,115,108,0,0,0,116,0,124,0,116, 1,131,2,115,28,116,2,100,1,160,3,116,4,124,0,131, @@ -1432,12 +1432,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 121,32,109,111,100,117,108,101,32,110,97,109,101,78,41,7, 218,10,105,115,105,110,115,116,97,110,99,101,218,3,115,116, 114,218,9,84,121,112,101,69,114,114,111,114,114,45,0,0, - 0,114,14,0,0,0,114,182,0,0,0,114,79,0,0,0, - 169,3,114,17,0,0,0,114,183,0,0,0,114,184,0,0, + 0,114,14,0,0,0,114,185,0,0,0,114,79,0,0,0, + 169,3,114,17,0,0,0,114,186,0,0,0,114,187,0,0, 0,114,10,0,0,0,114,10,0,0,0,114,11,0,0,0, 218,13,95,115,97,110,105,116,121,95,99,104,101,99,107,169, 3,0,0,115,22,0,0,0,0,2,10,1,18,1,8,1, - 8,1,8,1,10,1,10,1,4,1,8,2,12,1,114,197, + 8,1,8,1,10,1,10,1,4,1,8,2,12,1,114,200, 0,0,0,122,16,78,111,32,109,111,100,117,108,101,32,110, 97,109,101,100,32,122,4,123,33,114,125,99,2,0,0,0, 0,0,0,0,0,0,0,0,8,0,0,0,8,0,0,0, @@ -1462,7 +1462,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,114,92,0,0,0,114,67,0,0,0,114,141,0,0,0, 114,106,0,0,0,218,8,95,69,82,82,95,77,83,71,114, 45,0,0,0,218,19,77,111,100,117,108,101,78,111,116,70, - 111,117,110,100,69,114,114,111,114,114,192,0,0,0,114,159, + 111,117,110,100,69,114,114,111,114,114,195,0,0,0,114,159, 0,0,0,114,5,0,0,0,41,8,114,17,0,0,0,218, 7,105,109,112,111,114,116,95,114,164,0,0,0,114,130,0, 0,0,90,13,112,97,114,101,110,116,95,109,111,100,117,108, @@ -1472,7 +1472,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 117,110,108,111,99,107,101,100,188,3,0,0,115,42,0,0, 0,0,1,4,1,14,1,4,1,10,1,10,2,10,1,10, 1,10,1,2,1,10,1,14,1,16,1,20,1,10,1,8, - 1,20,2,8,1,4,2,10,1,22,1,114,202,0,0,0, + 1,20,2,8,1,4,2,10,1,22,1,114,205,0,0,0, 99,2,0,0,0,0,0,0,0,0,0,0,0,4,0,0, 0,10,0,0,0,67,0,0,0,115,106,0,0,0,116,0, 124,0,131,1,143,50,1,0,116,1,106,2,160,3,124,0, @@ -1488,14 +1488,14 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 101,32,105,110,32,115,121,115,46,109,111,100,117,108,101,115, 114,16,0,0,0,41,9,114,50,0,0,0,114,15,0,0, 0,114,92,0,0,0,114,34,0,0,0,218,14,95,78,69, - 69,68,83,95,76,79,65,68,73,78,71,114,202,0,0,0, - 114,45,0,0,0,114,200,0,0,0,114,65,0,0,0,41, - 4,114,17,0,0,0,114,201,0,0,0,114,96,0,0,0, + 69,68,83,95,76,79,65,68,73,78,71,114,205,0,0,0, + 114,45,0,0,0,114,203,0,0,0,114,65,0,0,0,41, + 4,114,17,0,0,0,114,204,0,0,0,114,96,0,0,0, 114,75,0,0,0,114,10,0,0,0,114,10,0,0,0,114, 11,0,0,0,218,14,95,102,105,110,100,95,97,110,100,95, 108,111,97,100,218,3,0,0,115,22,0,0,0,0,2,10, 1,14,1,8,1,32,2,8,1,4,1,2,255,4,2,12, - 2,8,1,114,204,0,0,0,114,22,0,0,0,99,3,0, + 2,8,1,114,207,0,0,0,114,22,0,0,0,99,3,0, 0,0,0,0,0,0,0,0,0,0,3,0,0,0,4,0, 0,0,67,0,0,0,115,42,0,0,0,116,0,124,0,124, 1,124,2,131,3,1,0,124,2,100,1,107,4,114,32,116, @@ -1520,11 +1520,11 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 103,32,95,95,112,97,99,107,97,103,101,95,95,32,105,102, 10,32,32,32,32,116,104,101,32,108,111,97,100,101,114,32, 100,105,100,32,110,111,116,46,10,10,32,32,32,32,114,22, - 0,0,0,41,4,114,197,0,0,0,114,185,0,0,0,114, - 204,0,0,0,218,11,95,103,99,100,95,105,109,112,111,114, - 116,114,196,0,0,0,114,10,0,0,0,114,10,0,0,0, - 114,11,0,0,0,114,205,0,0,0,234,3,0,0,115,8, - 0,0,0,0,9,12,1,8,1,12,1,114,205,0,0,0, + 0,0,0,41,4,114,200,0,0,0,114,188,0,0,0,114, + 207,0,0,0,218,11,95,103,99,100,95,105,109,112,111,114, + 116,114,199,0,0,0,114,10,0,0,0,114,10,0,0,0, + 114,11,0,0,0,114,208,0,0,0,234,3,0,0,115,8, + 0,0,0,0,9,12,1,8,1,12,1,114,208,0,0,0, 169,1,218,9,114,101,99,117,114,115,105,118,101,99,3,0, 0,0,0,0,0,0,1,0,0,0,8,0,0,0,11,0, 0,0,67,0,0,0,115,226,0,0,0,124,1,68,0,93, @@ -1561,21 +1561,21 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 109,32,108,105,115,116,39,39,122,8,73,116,101,109,32,105, 110,32,122,18,32,109,117,115,116,32,98,101,32,115,116,114, 44,32,110,111,116,32,250,1,42,218,7,95,95,97,108,108, - 95,95,84,114,206,0,0,0,114,179,0,0,0,78,41,16, - 114,193,0,0,0,114,194,0,0,0,114,1,0,0,0,114, - 195,0,0,0,114,14,0,0,0,114,4,0,0,0,218,16, + 95,95,84,114,209,0,0,0,114,182,0,0,0,78,41,16, + 114,196,0,0,0,114,197,0,0,0,114,1,0,0,0,114, + 198,0,0,0,114,14,0,0,0,114,4,0,0,0,218,16, 95,104,97,110,100,108,101,95,102,114,111,109,108,105,115,116, - 114,209,0,0,0,114,45,0,0,0,114,67,0,0,0,114, - 200,0,0,0,114,17,0,0,0,114,15,0,0,0,114,92, - 0,0,0,114,34,0,0,0,114,203,0,0,0,41,8,114, - 96,0,0,0,218,8,102,114,111,109,108,105,115,116,114,201, - 0,0,0,114,207,0,0,0,218,1,120,90,5,119,104,101, + 114,212,0,0,0,114,45,0,0,0,114,67,0,0,0,114, + 203,0,0,0,114,17,0,0,0,114,15,0,0,0,114,92, + 0,0,0,114,34,0,0,0,114,206,0,0,0,41,8,114, + 96,0,0,0,218,8,102,114,111,109,108,105,115,116,114,204, + 0,0,0,114,210,0,0,0,218,1,120,90,5,119,104,101, 114,101,90,9,102,114,111,109,95,110,97,109,101,90,3,101, 120,99,114,10,0,0,0,114,10,0,0,0,114,11,0,0, - 0,114,210,0,0,0,249,3,0,0,115,44,0,0,0,0, + 0,114,213,0,0,0,249,3,0,0,115,44,0,0,0,0, 10,8,1,10,1,4,1,12,2,4,1,28,2,8,1,14, 1,10,1,2,255,8,2,10,1,14,1,2,1,14,1,16, - 4,10,1,16,255,2,2,8,1,22,1,114,210,0,0,0, + 4,10,1,16,255,2,2,8,1,22,1,114,213,0,0,0, 99,1,0,0,0,0,0,0,0,0,0,0,0,3,0,0, 0,6,0,0,0,67,0,0,0,115,146,0,0,0,124,0, 160,0,100,1,161,1,125,1,124,0,160,0,100,2,161,1, @@ -1610,14 +1610,14 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 95,95,32,97,110,100,32,95,95,112,97,116,104,95,95,114, 1,0,0,0,114,141,0,0,0,114,128,0,0,0,114,22, 0,0,0,41,6,114,34,0,0,0,114,130,0,0,0,114, - 189,0,0,0,114,190,0,0,0,114,191,0,0,0,114,129, - 0,0,0,41,3,218,7,103,108,111,98,97,108,115,114,183, + 192,0,0,0,114,193,0,0,0,114,194,0,0,0,114,129, + 0,0,0,41,3,218,7,103,108,111,98,97,108,115,114,186, 0,0,0,114,95,0,0,0,114,10,0,0,0,114,10,0, 0,0,114,11,0,0,0,218,17,95,99,97,108,99,95,95, 95,112,97,99,107,97,103,101,95,95,30,4,0,0,115,38, 0,0,0,0,7,10,1,10,1,8,1,18,1,22,2,2, 0,2,254,6,3,4,1,8,1,6,2,6,2,2,0,2, - 254,6,3,8,1,8,1,14,1,114,216,0,0,0,114,10, + 254,6,3,8,1,8,1,14,1,114,219,0,0,0,114,10, 0,0,0,99,5,0,0,0,0,0,0,0,0,0,0,0, 9,0,0,0,5,0,0,0,67,0,0,0,115,180,0,0, 0,124,4,100,1,107,2,114,18,116,0,124,0,131,1,125, @@ -1662,18 +1662,18 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 96,32,119,111,117,108,100,32,104,97,118,101,32,97,32,39, 108,101,118,101,108,39,32,111,102,32,50,41,46,10,10,32, 32,32,32,114,22,0,0,0,78,114,128,0,0,0,114,141, - 0,0,0,41,9,114,205,0,0,0,114,216,0,0,0,218, - 9,112,97,114,116,105,116,105,111,110,114,181,0,0,0,114, + 0,0,0,41,9,114,208,0,0,0,114,219,0,0,0,218, + 9,112,97,114,116,105,116,105,111,110,114,184,0,0,0,114, 15,0,0,0,114,92,0,0,0,114,1,0,0,0,114,4, - 0,0,0,114,210,0,0,0,41,9,114,17,0,0,0,114, - 215,0,0,0,218,6,108,111,99,97,108,115,114,211,0,0, - 0,114,184,0,0,0,114,96,0,0,0,90,8,103,108,111, - 98,97,108,115,95,114,183,0,0,0,90,7,99,117,116,95, + 0,0,0,114,213,0,0,0,41,9,114,17,0,0,0,114, + 218,0,0,0,218,6,108,111,99,97,108,115,114,214,0,0, + 0,114,187,0,0,0,114,96,0,0,0,90,8,103,108,111, + 98,97,108,115,95,114,186,0,0,0,90,7,99,117,116,95, 111,102,102,114,10,0,0,0,114,10,0,0,0,114,11,0, 0,0,218,10,95,95,105,109,112,111,114,116,95,95,57,4, 0,0,115,30,0,0,0,0,11,8,1,10,2,16,1,8, 1,12,1,4,3,8,1,18,1,4,1,4,4,26,3,32, - 1,10,1,12,2,114,219,0,0,0,99,1,0,0,0,0, + 1,10,1,12,2,114,222,0,0,0,99,1,0,0,0,0, 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, 0,0,0,115,38,0,0,0,116,0,160,1,124,0,161,1, 125,1,124,1,100,0,107,8,114,30,116,2,100,1,124,0, @@ -1685,7 +1685,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,0,0,114,10,0,0,0,114,11,0,0,0,218,18,95, 98,117,105,108,116,105,110,95,102,114,111,109,95,110,97,109, 101,94,4,0,0,115,8,0,0,0,0,1,10,1,8,1, - 12,1,114,220,0,0,0,99,2,0,0,0,0,0,0,0, + 12,1,114,223,0,0,0,99,2,0,0,0,0,0,0,0, 0,0,0,0,10,0,0,0,5,0,0,0,67,0,0,0, 115,166,0,0,0,124,1,97,0,124,0,97,1,116,2,116, 1,131,1,125,2,116,1,106,3,160,4,161,0,68,0,93, @@ -1714,12 +1714,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 100,117,108,101,115,32,109,117,115,116,32,98,101,32,101,120, 112,108,105,99,105,116,108,121,32,112,97,115,115,101,100,32, 105,110,46,10,10,32,32,32,32,41,3,114,23,0,0,0, - 114,189,0,0,0,114,64,0,0,0,78,41,15,114,57,0, + 114,192,0,0,0,114,64,0,0,0,78,41,15,114,57,0, 0,0,114,15,0,0,0,114,14,0,0,0,114,92,0,0, - 0,218,5,105,116,101,109,115,114,193,0,0,0,114,78,0, + 0,218,5,105,116,101,109,115,114,196,0,0,0,114,78,0, 0,0,114,160,0,0,0,114,88,0,0,0,114,173,0,0, 0,114,142,0,0,0,114,148,0,0,0,114,1,0,0,0, - 114,220,0,0,0,114,5,0,0,0,41,10,218,10,115,121, + 114,223,0,0,0,114,5,0,0,0,41,10,218,10,115,121, 115,95,109,111,100,117,108,101,218,11,95,105,109,112,95,109, 111,100,117,108,101,90,11,109,111,100,117,108,101,95,116,121, 112,101,114,17,0,0,0,114,96,0,0,0,114,109,0,0, @@ -1730,7 +1730,7 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 218,6,95,115,101,116,117,112,101,4,0,0,115,36,0,0, 0,0,9,4,1,4,3,8,1,18,1,10,1,10,1,6, 1,10,1,6,2,2,1,10,1,12,3,10,1,8,1,10, - 1,10,2,10,1,114,224,0,0,0,99,2,0,0,0,0, + 1,10,2,10,1,114,227,0,0,0,99,2,0,0,0,0, 0,0,0,0,0,0,0,2,0,0,0,3,0,0,0,67, 0,0,0,115,38,0,0,0,116,0,124,0,124,1,131,2, 1,0,116,1,106,2,160,3,116,4,161,1,1,0,116,1, @@ -1738,12 +1738,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 122,48,73,110,115,116,97,108,108,32,105,109,112,111,114,116, 101,114,115,32,102,111,114,32,98,117,105,108,116,105,110,32, 97,110,100,32,102,114,111,122,101,110,32,109,111,100,117,108, - 101,115,78,41,6,114,224,0,0,0,114,15,0,0,0,114, - 188,0,0,0,114,120,0,0,0,114,160,0,0,0,114,173, - 0,0,0,41,2,114,222,0,0,0,114,223,0,0,0,114, + 101,115,78,41,6,114,227,0,0,0,114,15,0,0,0,114, + 191,0,0,0,114,120,0,0,0,114,160,0,0,0,114,173, + 0,0,0,41,2,114,225,0,0,0,114,226,0,0,0,114, 10,0,0,0,114,10,0,0,0,114,11,0,0,0,218,8, 95,105,110,115,116,97,108,108,136,4,0,0,115,6,0,0, - 0,0,2,10,2,12,1,114,225,0,0,0,99,0,0,0, + 0,0,2,10,2,12,1,114,228,0,0,0,99,0,0,0, 0,0,0,0,0,0,0,0,0,1,0,0,0,4,0,0, 0,67,0,0,0,115,32,0,0,0,100,1,100,2,108,0, 125,0,124,0,97,1,124,0,160,2,116,3,106,4,116,5, @@ -1754,12 +1754,12 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 32,97,99,99,101,115,115,114,22,0,0,0,78,41,6,218, 26,95,102,114,111,122,101,110,95,105,109,112,111,114,116,108, 105,98,95,101,120,116,101,114,110,97,108,114,126,0,0,0, - 114,225,0,0,0,114,15,0,0,0,114,92,0,0,0,114, - 1,0,0,0,41,1,114,226,0,0,0,114,10,0,0,0, + 114,228,0,0,0,114,15,0,0,0,114,92,0,0,0,114, + 1,0,0,0,41,1,114,229,0,0,0,114,10,0,0,0, 114,10,0,0,0,114,11,0,0,0,218,27,95,105,110,115, 116,97,108,108,95,101,120,116,101,114,110,97,108,95,105,109, 112,111,114,116,101,114,115,144,4,0,0,115,6,0,0,0, - 0,3,8,1,4,1,114,227,0,0,0,41,2,78,78,41, + 0,3,8,1,4,1,114,230,0,0,0,41,2,78,78,41, 1,78,41,2,78,114,22,0,0,0,41,4,78,78,114,10, 0,0,0,114,22,0,0,0,41,50,114,3,0,0,0,114, 126,0,0,0,114,12,0,0,0,114,18,0,0,0,114,59, @@ -1771,13 +1771,13 @@ const unsigned char _Py_M__importlib_bootstrap[] = { 0,0,0,114,142,0,0,0,114,148,0,0,0,114,152,0, 0,0,114,107,0,0,0,114,93,0,0,0,114,158,0,0, 0,114,159,0,0,0,114,94,0,0,0,114,160,0,0,0, - 114,173,0,0,0,114,178,0,0,0,114,185,0,0,0,114, - 187,0,0,0,114,192,0,0,0,114,197,0,0,0,90,15, + 114,173,0,0,0,114,178,0,0,0,114,188,0,0,0,114, + 190,0,0,0,114,195,0,0,0,114,200,0,0,0,90,15, 95,69,82,82,95,77,83,71,95,80,82,69,70,73,88,114, - 199,0,0,0,114,202,0,0,0,218,6,111,98,106,101,99, - 116,114,203,0,0,0,114,204,0,0,0,114,205,0,0,0, - 114,210,0,0,0,114,216,0,0,0,114,219,0,0,0,114, - 220,0,0,0,114,224,0,0,0,114,225,0,0,0,114,227, + 202,0,0,0,114,205,0,0,0,218,6,111,98,106,101,99, + 116,114,206,0,0,0,114,207,0,0,0,114,208,0,0,0, + 114,213,0,0,0,114,219,0,0,0,114,222,0,0,0,114, + 223,0,0,0,114,227,0,0,0,114,228,0,0,0,114,230, 0,0,0,114,10,0,0,0,114,10,0,0,0,114,10,0, 0,0,114,11,0,0,0,218,8,60,109,111,100,117,108,101, 62,1,0,0,0,115,94,0,0,0,4,24,4,2,8,8, diff --git a/Python/pylifecycle.c b/Python/pylifecycle.c index 01344db..6dc684b 100644 --- a/Python/pylifecycle.c +++ b/Python/pylifecycle.c @@ -587,6 +587,12 @@ pycore_init_types(void) if (!_PyContext_Init()) { return _Py_INIT_ERR("can't init context"); } + + err = _PyErr_Init(); + if (_Py_INIT_FAILED(err)) { + return err; + } + return _Py_INIT_OK(); } @@ -1462,6 +1468,12 @@ new_interpreter(PyThreadState **tstate_p) return err; } + err = _PyErr_Init(); + if (_Py_INIT_FAILED(err)) { + return err; + } + + /* XXX The following is lax in error checking */ PyObject *modules = PyDict_New(); if (modules == NULL) { diff --git a/Python/sysmodule.c b/Python/sysmodule.c index 1290164..1735b90 100644 --- a/Python/sysmodule.c +++ b/Python/sysmodule.c @@ -375,6 +375,30 @@ sys_exc_info_impl(PyObject *module) /*[clinic input] +sys.unraisablehook + + unraisable: object + / + +Handle an unraisable exception. + +The unraisable argument has the following attributes: + +* exc_type: Exception type. +* exc_value: Exception value. +* exc_tb: Exception traceback, can be None. +* obj: Object causing the exception, can be None. +[clinic start generated code]*/ + +static PyObject * +sys_unraisablehook(PyObject *module, PyObject *unraisable) +/*[clinic end generated code: output=bb92838b32abaa14 input=fdbdb47fdd0bee06]*/ +{ + return _PyErr_WriteUnraisableDefaultHook(unraisable); +} + + +/*[clinic input] sys.exit status: object = NULL @@ -1672,6 +1696,7 @@ static PyMethodDef sys_methods[] = { METH_VARARGS | METH_KEYWORDS, set_asyncgen_hooks_doc}, SYS_GET_ASYNCGEN_HOOKS_METHODDEF SYS_GETANDROIDAPILEVEL_METHODDEF + SYS_UNRAISABLEHOOK_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -2369,6 +2394,9 @@ _PySys_InitCore(_PyRuntimeState *runtime, PyInterpreterState *interp, SET_SYS_FROM_STRING_BORROW( "__breakpointhook__", PyDict_GetItemString(sysdict, "breakpointhook")); + SET_SYS_FROM_STRING_BORROW("__unraisablehook__", + PyDict_GetItemString(sysdict, "unraisablehook")); + SET_SYS_FROM_STRING("version", PyUnicode_FromString(Py_GetVersion())); SET_SYS_FROM_STRING("hexversion", |