diff --git a/Doc/whatsnew/3.6.rst b/Doc/whatsnew/3.6.rst index 847b50140a6..570dc3ed6fe 100644 --- a/Doc/whatsnew/3.6.rst +++ b/Doc/whatsnew/3.6.rst @@ -1852,10 +1852,10 @@ Build and C API Changes * The :c:func:`PyUnicode_FSConverter` and :c:func:`PyUnicode_FSDecoder` functions will now accept :term:`path-like objects `. -* The ``PyExc_RecursionErrorInst`` singleton that was part of the public API - has been removed as its members being never cleared may cause a segfault - during finalization of the interpreter. Contributed by Xavier de Gaye in - :issue:`22898` and :issue:`30697`. +* The ``PyExc_RecursionErrorInst`` singleton is not used anymore as its members + being never cleared may cause a segfault during finalization of the + interpreter. Contributed by Xavier de Gaye in :issue:`22898` and + :issue:`30697`. Other Improvements diff --git a/Include/pyerrors.h b/Include/pyerrors.h index c28c1373f82..8c1dbc5047b 100644 --- a/Include/pyerrors.h +++ b/Include/pyerrors.h @@ -219,6 +219,8 @@ PyAPI_DATA(PyObject *) PyExc_IOError; PyAPI_DATA(PyObject *) PyExc_WindowsError; #endif +PyAPI_DATA(PyObject *) PyExc_RecursionErrorInst; + /* Predefined warning categories */ PyAPI_DATA(PyObject *) PyExc_Warning; PyAPI_DATA(PyObject *) PyExc_UserWarning; diff --git a/Misc/NEWS.d/next/C API/2017-12-20-15-23-06.bpo-30697.v9FmgG.rst b/Misc/NEWS.d/next/C API/2017-12-20-15-23-06.bpo-30697.v9FmgG.rst new file mode 100644 index 00000000000..28f74ad4f30 --- /dev/null +++ b/Misc/NEWS.d/next/C API/2017-12-20-15-23-06.bpo-30697.v9FmgG.rst @@ -0,0 +1 @@ +Restore PyExc_RecursionErrorInst in 3.6 diff --git a/Objects/exceptions.c b/Objects/exceptions.c index df4899372a5..271e293e325 100644 --- a/Objects/exceptions.c +++ b/Objects/exceptions.c @@ -2430,6 +2430,12 @@ SimpleExtendsException(PyExc_Warning, ResourceWarning, +/* Pre-computed RecursionError instance for when recursion depth is reached. + Meant to be used when normalizing the exception for exceeding the recursion + depth will cause its own infinite recursion. +*/ +PyObject *PyExc_RecursionErrorInst = NULL; + #define PRE_INIT(TYPE) \ if (!(_PyExc_ ## TYPE.tp_flags & Py_TPFLAGS_READY)) { \ if (PyType_Ready(&_PyExc_ ## TYPE) < 0) \ @@ -2691,11 +2697,37 @@ _PyExc_Init(PyObject *bltinmod) ADD_ERRNO(TimeoutError, ETIMEDOUT); preallocate_memerrors(); + + if (!PyExc_RecursionErrorInst) { + PyExc_RecursionErrorInst = BaseException_new(&_PyExc_RecursionError, NULL, NULL); + if (!PyExc_RecursionErrorInst) + Py_FatalError("Cannot pre-allocate RecursionError instance for " + "recursion errors"); + else { + PyBaseExceptionObject *err_inst = + (PyBaseExceptionObject *)PyExc_RecursionErrorInst; + PyObject *args_tuple; + PyObject *exc_message; + exc_message = PyUnicode_FromString("maximum recursion depth exceeded"); + if (!exc_message) + Py_FatalError("cannot allocate argument for RecursionError " + "pre-allocation"); + args_tuple = PyTuple_Pack(1, exc_message); + if (!args_tuple) + Py_FatalError("cannot allocate tuple for RecursionError " + "pre-allocation"); + Py_DECREF(exc_message); + if (BaseException_init(err_inst, args_tuple, NULL)) + Py_FatalError("init of pre-allocated RecursionError failed"); + Py_DECREF(args_tuple); + } + } } void _PyExc_Fini(void) { + Py_CLEAR(PyExc_RecursionErrorInst); free_preallocated_memerrors(); Py_CLEAR(errnomap); } diff --git a/PC/python3.def b/PC/python3.def index 4fc4a6814ee..ff70718fc37 100644 --- a/PC/python3.def +++ b/PC/python3.def @@ -224,6 +224,7 @@ EXPORTS PyExc_PermissionError=python36.PyExc_PermissionError DATA PyExc_ProcessLookupError=python36.PyExc_ProcessLookupError DATA PyExc_RecursionError=python36.PyExc_RecursionError DATA + PyExc_RecursionErrorInst=python36.PyExc_RecursionErrorInst DATA PyExc_ReferenceError=python36.PyExc_ReferenceError DATA PyExc_ResourceWarning=python36.PyExc_ResourceWarning DATA PyExc_RuntimeError=python36.PyExc_RuntimeError DATA