99#include "Python.h"
1010
1111/* Forward declaration (for atexit_cleanup) */
12- static PyObject * atexit_clear (PyObject * );
12+ static PyObject * atexit_clear (PyObject * , PyObject * );
1313/* Forward declaration (for atexit_callfuncs) */
14- static void atexit_cleanup (void );
14+ static void atexit_cleanup (PyObject * );
15+ /* Forward declaration of module object */
16+ static struct PyModuleDef atexitmodule ;
1517
1618/* ===================================================================== */
1719/* Callback machinery. */
@@ -22,9 +24,14 @@ typedef struct {
2224 PyObject * kwargs ;
2325} atexit_callback ;
2426
25- static atexit_callback * * atexit_callbacks ;
26- static int ncallbacks = 0 ;
27- static int callback_len = 32 ;
27+ typedef struct {
28+ atexit_callback * * atexit_callbacks ;
29+ int ncallbacks ;
30+ int callback_len ;
31+ } atexitmodule_state ;
32+
33+ #define GET_ATEXIT_STATE (mod ) ((atexitmodule_state*)PyModule_GetState(mod))
34+
2835
2936/* Installed into pythonrun.c's atexit mechanism */
3037
@@ -33,14 +40,22 @@ atexit_callfuncs(void)
3340{
3441 PyObject * exc_type = NULL , * exc_value , * exc_tb , * r ;
3542 atexit_callback * cb ;
43+ PyObject * module ;
44+ atexitmodule_state * modstate ;
3645 int i ;
37-
38- if (ncallbacks == 0 )
46+
47+ module = PyState_FindModule (& atexitmodule );
48+ if (module == NULL )
3949 return ;
40-
41- for (i = ncallbacks - 1 ; i >= 0 ; i -- )
50+ modstate = GET_ATEXIT_STATE (module );
51+
52+ if (modstate -> ncallbacks == 0 )
53+ return ;
54+
55+
56+ for (i = modstate -> ncallbacks - 1 ; i >= 0 ; i -- )
4257 {
43- cb = atexit_callbacks [i ];
58+ cb = modstate -> atexit_callbacks [i ];
4459 if (cb == NULL )
4560 continue ;
4661
@@ -61,28 +76,32 @@ atexit_callfuncs(void)
6176 }
6277 }
6378 }
64-
65- atexit_cleanup ();
79+
80+ atexit_cleanup (module );
6681
6782 if (exc_type )
6883 PyErr_Restore (exc_type , exc_value , exc_tb );
6984}
7085
7186static void
72- atexit_delete_cb (int i )
87+ atexit_delete_cb (PyObject * self , int i )
7388{
74- atexit_callback * cb = atexit_callbacks [i ];
75- atexit_callbacks [i ] = NULL ;
89+ atexitmodule_state * modstate ;
90+ atexit_callback * cb ;
91+
92+ modstate = GET_ATEXIT_STATE (self );
93+ cb = modstate -> atexit_callbacks [i ];
94+ modstate -> atexit_callbacks [i ] = NULL ;
7695 Py_DECREF (cb -> func );
7796 Py_DECREF (cb -> args );
7897 Py_XDECREF (cb -> kwargs );
79- PyMem_Free (cb );
98+ PyMem_Free (cb );
8099}
81100
82101static void
83- atexit_cleanup (void )
102+ atexit_cleanup (PyObject * self )
84103{
85- PyObject * r = atexit_clear (NULL );
104+ PyObject * r = atexit_clear (self , NULL );
86105 Py_DECREF (r );
87106}
88107
@@ -103,32 +122,35 @@ Register a function to be executed upon normal program termination\n\
103122static PyObject *
104123atexit_register (PyObject * self , PyObject * args , PyObject * kwargs )
105124{
125+ atexitmodule_state * modstate ;
106126 atexit_callback * new_callback ;
107127 PyObject * func = NULL ;
108-
109- if (ncallbacks >= callback_len ) {
128+
129+ modstate = GET_ATEXIT_STATE (self );
130+
131+ if (modstate -> ncallbacks >= modstate -> callback_len ) {
110132 atexit_callback * * r ;
111- callback_len += 16 ;
112- r = (atexit_callback * * )PyMem_Realloc (atexit_callbacks ,
113- sizeof (atexit_callback * ) * callback_len );
133+ modstate -> callback_len += 16 ;
134+ r = (atexit_callback * * )PyMem_Realloc (modstate -> atexit_callbacks ,
135+ sizeof (atexit_callback * ) * modstate -> callback_len );
114136 if (r == NULL )
115137 return PyErr_NoMemory ();
116- atexit_callbacks = r ;
138+ modstate -> atexit_callbacks = r ;
117139 }
118-
140+
119141 if (PyTuple_GET_SIZE (args ) == 0 ) {
120142 PyErr_SetString (PyExc_TypeError ,
121143 "register() takes at least 1 argument (0 given)" );
122144 return NULL ;
123145 }
124-
146+
125147 func = PyTuple_GET_ITEM (args , 0 );
126148 if (!PyCallable_Check (func )) {
127149 PyErr_SetString (PyExc_TypeError ,
128150 "the first argument must be callable" );
129151 return NULL ;
130152 }
131-
153+
132154 new_callback = PyMem_Malloc (sizeof (atexit_callback ));
133155 if (new_callback == NULL )
134156 return PyErr_NoMemory ();
@@ -142,9 +164,9 @@ atexit_register(PyObject *self, PyObject *args, PyObject *kwargs)
142164 new_callback -> kwargs = kwargs ;
143165 Py_INCREF (func );
144166 Py_XINCREF (kwargs );
145-
146- atexit_callbacks [ncallbacks ++ ] = new_callback ;
147-
167+
168+ modstate -> atexit_callbacks [modstate -> ncallbacks ++ ] = new_callback ;
169+
148170 Py_INCREF (func );
149171 return func ;
150172}
@@ -155,7 +177,7 @@ PyDoc_STRVAR(atexit_run_exitfuncs__doc__,
155177Run all registered exit functions." );
156178
157179static PyObject *
158- atexit_run_exitfuncs (PyObject * self )
180+ atexit_run_exitfuncs (PyObject * self , PyObject * unused )
159181{
160182 atexit_callfuncs ();
161183 if (PyErr_Occurred ())
@@ -169,20 +191,22 @@ PyDoc_STRVAR(atexit_clear__doc__,
169191Clear the list of previously registered exit functions." );
170192
171193static PyObject *
172- atexit_clear (PyObject * self )
194+ atexit_clear (PyObject * self , PyObject * unused )
173195{
196+ atexitmodule_state * modstate ;
174197 atexit_callback * cb ;
175198 int i ;
176-
177- for (i = 0 ; i < ncallbacks ; i ++ )
178- {
179- cb = atexit_callbacks [i ];
199+
200+ modstate = GET_ATEXIT_STATE (self );
201+
202+ for (i = 0 ; i < modstate -> ncallbacks ; i ++ ) {
203+ cb = modstate -> atexit_callbacks [i ];
180204 if (cb == NULL )
181205 continue ;
182-
183- atexit_delete_cb (i );
206+
207+ atexit_delete_cb (self , i );
184208 }
185- ncallbacks = 0 ;
209+ modstate -> ncallbacks = 0 ;
186210 Py_RETURN_NONE ;
187211}
188212
@@ -197,20 +221,23 @@ atexit.register\n\
197221static PyObject *
198222atexit_unregister (PyObject * self , PyObject * func )
199223{
224+ atexitmodule_state * modstate ;
200225 atexit_callback * cb ;
201226 int i , eq ;
202-
203- for (i = 0 ; i < ncallbacks ; i ++ )
227+
228+ modstate = GET_ATEXIT_STATE (self );
229+
230+ for (i = 0 ; i < modstate -> ncallbacks ; i ++ )
204231 {
205- cb = atexit_callbacks [i ];
232+ cb = modstate -> atexit_callbacks [i ];
206233 if (cb == NULL )
207234 continue ;
208-
235+
209236 eq = PyObject_RichCompareBool (cb -> func , func , Py_EQ );
210237 if (eq < 0 )
211238 return NULL ;
212239 if (eq )
213- atexit_delete_cb (i );
240+ atexit_delete_cb (self , i );
214241 }
215242 Py_RETURN_NONE ;
216243}
@@ -242,7 +269,7 @@ static struct PyModuleDef atexitmodule = {
242269 PyModuleDef_HEAD_INIT ,
243270 "atexit" ,
244271 atexit__doc__ ,
245- -1 ,
272+ sizeof ( atexitmodule_state ) ,
246273 atexit_methods ,
247274 NULL ,
248275 NULL ,
@@ -254,15 +281,20 @@ PyMODINIT_FUNC
254281PyInit_atexit (void )
255282{
256283 PyObject * m ;
257-
258- atexit_callbacks = PyMem_New (atexit_callback * , callback_len );
259- if (atexit_callbacks == NULL )
260- return NULL ;
284+ atexitmodule_state * modstate ;
261285
262286 m = PyModule_Create (& atexitmodule );
263287 if (m == NULL )
264288 return NULL ;
265-
289+
290+ modstate = GET_ATEXIT_STATE (m );
291+ modstate -> callback_len = 32 ;
292+ modstate -> ncallbacks = 0 ;
293+ modstate -> atexit_callbacks = PyMem_New (atexit_callback * ,
294+ modstate -> callback_len );
295+ if (modstate -> atexit_callbacks == NULL )
296+ return NULL ;
297+
266298 _Py_PyAtExit (atexit_callfuncs );
267299 return m ;
268300}
0 commit comments