summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Doc/c-api/exceptions.rst5
-rw-r--r--Doc/library/sys.rst33
-rw-r--r--Doc/whatsnew/3.8.rst10
-rw-r--r--Include/internal/pycore_pylifecycle.h4
-rw-r--r--Lib/test/test_sys.py80
-rw-r--r--Misc/NEWS.d/next/Library/2019-05-08-12-51-37.bpo-36829.8enFMA.rst5
-rw-r--r--Modules/_testcapimodule.c15
-rw-r--r--Python/clinic/sysmodule.c.h18
-rw-r--r--Python/errors.c278
-rw-r--r--Python/importlib.h120
-rw-r--r--Python/pylifecycle.c12
-rw-r--r--Python/sysmodule.c28
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",