@@ -19,8 +19,13 @@ PyObject *PyExc_IOError = NULL;
1919PyObject * PyExc_WindowsError = NULL ;
2020#endif
2121
22- /* The dict map from errno codes to OSError subclasses */
23- static PyObject * errnomap = NULL ;
22+
23+ static struct _Py_exc_state *
24+ get_exc_state (void )
25+ {
26+ PyInterpreterState * interp = _PyInterpreterState_GET ();
27+ return & interp -> exc_state ;
28+ }
2429
2530
2631/* NOTE: If the exception class hierarchy changes, don't forget to update
@@ -985,10 +990,11 @@ OSError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
985990 ))
986991 goto error ;
987992
993+ struct _Py_exc_state * state = get_exc_state ();
988994 if (myerrno && PyLong_Check (myerrno ) &&
989- errnomap && (PyObject * ) type == PyExc_OSError ) {
995+ state -> errnomap && (PyObject * ) type == PyExc_OSError ) {
990996 PyObject * newtype ;
991- newtype = PyDict_GetItemWithError (errnomap , myerrno );
997+ newtype = PyDict_GetItemWithError (state -> errnomap , myerrno );
992998 if (newtype ) {
993999 assert (PyType_Check (newtype ));
9941000 type = (PyTypeObject * ) newtype ;
@@ -2274,8 +2280,6 @@ SimpleExtendsException(PyExc_Exception, ReferenceError,
22742280 */
22752281
22762282#define MEMERRORS_SAVE 16
2277- static PyBaseExceptionObject * memerrors_freelist = NULL ;
2278- static int memerrors_numfree = 0 ;
22792283
22802284static PyObject *
22812285MemoryError_new (PyTypeObject * type , PyObject * args , PyObject * kwds )
@@ -2284,16 +2288,22 @@ MemoryError_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
22842288
22852289 if (type != (PyTypeObject * ) PyExc_MemoryError )
22862290 return BaseException_new (type , args , kwds );
2287- if (memerrors_freelist == NULL )
2291+
2292+ struct _Py_exc_state * state = get_exc_state ();
2293+ if (state -> memerrors_freelist == NULL ) {
22882294 return BaseException_new (type , args , kwds );
2295+ }
2296+
22892297 /* Fetch object from freelist and revive it */
2290- self = memerrors_freelist ;
2298+ self = state -> memerrors_freelist ;
22912299 self -> args = PyTuple_New (0 );
22922300 /* This shouldn't happen since the empty tuple is persistent */
2293- if (self -> args == NULL )
2301+ if (self -> args == NULL ) {
22942302 return NULL ;
2295- memerrors_freelist = (PyBaseExceptionObject * ) self -> dict ;
2296- memerrors_numfree -- ;
2303+ }
2304+
2305+ state -> memerrors_freelist = (PyBaseExceptionObject * ) self -> dict ;
2306+ state -> memerrors_numfree -- ;
22972307 self -> dict = NULL ;
22982308 _Py_NewReference ((PyObject * )self );
22992309 _PyObject_GC_TRACK (self );
@@ -2305,12 +2315,15 @@ MemoryError_dealloc(PyBaseExceptionObject *self)
23052315{
23062316 _PyObject_GC_UNTRACK (self );
23072317 BaseException_clear (self );
2308- if (memerrors_numfree >= MEMERRORS_SAVE )
2318+
2319+ struct _Py_exc_state * state = get_exc_state ();
2320+ if (state -> memerrors_numfree >= MEMERRORS_SAVE ) {
23092321 Py_TYPE (self )-> tp_free ((PyObject * )self );
2322+ }
23102323 else {
2311- self -> dict = (PyObject * ) memerrors_freelist ;
2312- memerrors_freelist = self ;
2313- memerrors_numfree ++ ;
2324+ self -> dict = (PyObject * ) state -> memerrors_freelist ;
2325+ state -> memerrors_freelist = self ;
2326+ state -> memerrors_numfree ++ ;
23142327 }
23152328}
23162329
@@ -2335,11 +2348,11 @@ preallocate_memerrors(void)
23352348}
23362349
23372350static void
2338- free_preallocated_memerrors (void )
2351+ free_preallocated_memerrors (struct _Py_exc_state * state )
23392352{
2340- while (memerrors_freelist != NULL ) {
2341- PyObject * self = (PyObject * ) memerrors_freelist ;
2342- memerrors_freelist = (PyBaseExceptionObject * ) memerrors_freelist -> dict ;
2353+ while (state -> memerrors_freelist != NULL ) {
2354+ PyObject * self = (PyObject * ) state -> memerrors_freelist ;
2355+ state -> memerrors_freelist = (PyBaseExceptionObject * )state -> memerrors_freelist -> dict ;
23432356 Py_TYPE (self )-> tp_free ((PyObject * )self );
23442357 }
23452358}
@@ -2507,8 +2520,10 @@ SimpleExtendsException(PyExc_Warning, ResourceWarning,
25072520#endif /* MS_WINDOWS */
25082521
25092522PyStatus
2510- _PyExc_Init (void )
2523+ _PyExc_Init (PyThreadState * tstate )
25112524{
2525+ struct _Py_exc_state * state = & tstate -> interp -> exc_state ;
2526+
25122527#define PRE_INIT (TYPE ) \
25132528 if (!(_PyExc_ ## TYPE.tp_flags & Py_TPFLAGS_READY)) { \
25142529 if (PyType_Ready(&_PyExc_ ## TYPE) < 0) { \
@@ -2521,7 +2536,7 @@ _PyExc_Init(void)
25212536 do { \
25222537 PyObject *_code = PyLong_FromLong(CODE); \
25232538 assert(_PyObject_RealIsSubclass(PyExc_ ## TYPE, PyExc_OSError)); \
2524- if (!_code || PyDict_SetItem(errnomap, _code, PyExc_ ## TYPE)) \
2539+ if (!_code || PyDict_SetItem(state-> errnomap, _code, PyExc_ ## TYPE)) \
25252540 return _PyStatus_ERR("errmap insertion problem."); \
25262541 Py_DECREF(_code); \
25272542 } while (0)
@@ -2595,15 +2610,14 @@ _PyExc_Init(void)
25952610 PRE_INIT (TimeoutError );
25962611
25972612 if (preallocate_memerrors () < 0 ) {
2598- return _PyStatus_ERR ( "Could not preallocate MemoryError object" );
2613+ return _PyStatus_NO_MEMORY ( );
25992614 }
26002615
26012616 /* Add exceptions to errnomap */
2602- if (!errnomap ) {
2603- errnomap = PyDict_New ();
2604- if (!errnomap ) {
2605- return _PyStatus_ERR ("Cannot allocate map from errnos to OSError subclasses" );
2606- }
2617+ assert (state -> errnomap == NULL );
2618+ state -> errnomap = PyDict_New ();
2619+ if (!state -> errnomap ) {
2620+ return _PyStatus_NO_MEMORY ();
26072621 }
26082622
26092623 ADD_ERRNO (BlockingIOError , EAGAIN );
@@ -2741,10 +2755,11 @@ _PyBuiltins_AddExceptions(PyObject *bltinmod)
27412755}
27422756
27432757void
2744- _PyExc_Fini (void )
2758+ _PyExc_Fini (PyThreadState * tstate )
27452759{
2746- free_preallocated_memerrors ();
2747- Py_CLEAR (errnomap );
2760+ struct _Py_exc_state * state = & tstate -> interp -> exc_state ;
2761+ free_preallocated_memerrors (state );
2762+ Py_CLEAR (state -> errnomap );
27482763}
27492764
27502765/* Helper to do the equivalent of "raise X from Y" in C, but always using
0 commit comments