7
7
*/
8
8
9
9
#include "Python.h"
10
- #include "pycore_interp.h" // PyInterpreterState.atexit_func
10
+ #include "pycore_initconfig.h" // _PyStatus_NO_MEMORY
11
+ #include "pycore_interp.h" // PyInterpreterState.atexit
11
12
#include "pycore_pystate.h" // _PyInterpreterState_GET
12
13
13
14
/* ===================================================================== */
14
15
/* Callback machinery. */
15
16
16
- typedef struct {
17
- PyObject * func ;
18
- PyObject * args ;
19
- PyObject * kwargs ;
20
- } atexit_callback ;
21
-
22
- struct atexit_state {
23
- atexit_callback * * atexit_callbacks ;
24
- int ncallbacks ;
25
- int callback_len ;
26
- };
27
-
28
17
static inline struct atexit_state *
29
- get_atexit_state (PyObject * module )
18
+ get_atexit_state (void )
30
19
{
31
- void * state = PyModule_GetState (module );
32
- assert (state != NULL );
33
- return (struct atexit_state * )state ;
20
+ PyInterpreterState * interp = _PyInterpreterState_GET ();
21
+ return & interp -> atexit ;
34
22
}
35
23
36
24
37
25
static void
38
26
atexit_delete_cb (struct atexit_state * state , int i )
39
27
{
40
- atexit_callback * cb = state -> atexit_callbacks [i ];
41
- state -> atexit_callbacks [i ] = NULL ;
28
+ atexit_callback * cb = state -> callbacks [i ];
29
+ state -> callbacks [i ] = NULL ;
42
30
43
31
Py_DECREF (cb -> func );
44
32
Py_DECREF (cb -> args );
@@ -53,7 +41,7 @@ atexit_cleanup(struct atexit_state *state)
53
41
{
54
42
atexit_callback * cb ;
55
43
for (int i = 0 ; i < state -> ncallbacks ; i ++ ) {
56
- cb = state -> atexit_callbacks [i ];
44
+ cb = state -> callbacks [i ];
57
45
if (cb == NULL )
58
46
continue ;
59
47
@@ -62,25 +50,45 @@ atexit_cleanup(struct atexit_state *state)
62
50
state -> ncallbacks = 0 ;
63
51
}
64
52
65
- /* Installed into pylifecycle.c's atexit mechanism */
66
53
67
- static void
68
- atexit_callfuncs ( PyObject * module , int ignore_exc )
54
+ PyStatus
55
+ _PyAtExit_Init ( PyThreadState * tstate )
69
56
{
70
- assert (!PyErr_Occurred ());
57
+ struct atexit_state * state = & tstate -> interp -> atexit ;
58
+ // _PyAtExit_Init() must only be called once
59
+ assert (state -> callbacks == NULL );
71
60
72
- if (module == NULL ) {
73
- return ;
61
+ state -> callback_len = 32 ;
62
+ state -> ncallbacks = 0 ;
63
+ state -> callbacks = PyMem_New (atexit_callback * , state -> callback_len );
64
+ if (state -> callbacks == NULL ) {
65
+ return _PyStatus_NO_MEMORY ();
74
66
}
67
+ return _PyStatus_OK ();
68
+ }
69
+
70
+
71
+ void
72
+ _PyAtExit_Fini (PyInterpreterState * interp )
73
+ {
74
+ struct atexit_state * state = & interp -> atexit ;
75
+ atexit_cleanup (state );
76
+ PyMem_Free (state -> callbacks );
77
+ }
78
+
79
+
80
+ static void
81
+ atexit_callfuncs (struct atexit_state * state , int ignore_exc )
82
+ {
83
+ assert (!PyErr_Occurred ());
75
84
76
- struct atexit_state * state = get_atexit_state (module );
77
85
if (state -> ncallbacks == 0 ) {
78
86
return ;
79
87
}
80
88
81
89
PyObject * exc_type = NULL , * exc_value , * exc_tb ;
82
90
for (int i = state -> ncallbacks - 1 ; i >= 0 ; i -- ) {
83
- atexit_callback * cb = state -> atexit_callbacks [i ];
91
+ atexit_callback * cb = state -> callbacks [i ];
84
92
if (cb == NULL ) {
85
93
continue ;
86
94
}
@@ -125,15 +133,17 @@ atexit_callfuncs(PyObject *module, int ignore_exc)
125
133
126
134
127
135
void
128
- _PyAtExit_Call (PyObject * module )
136
+ _PyAtExit_Call (PyThreadState * tstate )
129
137
{
130
- atexit_callfuncs (module , 1 );
138
+ struct atexit_state * state = & tstate -> interp -> atexit ;
139
+ atexit_callfuncs (state , 1 );
131
140
}
132
141
133
142
134
143
/* ===================================================================== */
135
144
/* Module methods. */
136
145
146
+
137
147
PyDoc_STRVAR (atexit_register__doc__ ,
138
148
"register(func, *args, **kwargs) -> func\n\
139
149
\n\
@@ -161,15 +171,15 @@ atexit_register(PyObject *module, PyObject *args, PyObject *kwargs)
161
171
return NULL ;
162
172
}
163
173
164
- struct atexit_state * state = get_atexit_state (module );
174
+ struct atexit_state * state = get_atexit_state ();
165
175
if (state -> ncallbacks >= state -> callback_len ) {
166
176
atexit_callback * * r ;
167
177
state -> callback_len += 16 ;
168
- r = (atexit_callback * * ) PyMem_Realloc ( state -> atexit_callbacks ,
169
- sizeof (atexit_callback * ) * state -> callback_len );
178
+ size_t size = sizeof (atexit_callback * ) * ( size_t ) state -> callback_len ;
179
+ r = (atexit_callback * * ) PyMem_Realloc ( state -> callbacks , size );
170
180
if (r == NULL )
171
181
return PyErr_NoMemory ();
172
- state -> atexit_callbacks = r ;
182
+ state -> callbacks = r ;
173
183
}
174
184
175
185
atexit_callback * callback = PyMem_Malloc (sizeof (atexit_callback ));
@@ -185,7 +195,7 @@ atexit_register(PyObject *module, PyObject *args, PyObject *kwargs)
185
195
callback -> func = Py_NewRef (func );
186
196
callback -> kwargs = Py_XNewRef (kwargs );
187
197
188
- state -> atexit_callbacks [state -> ncallbacks ++ ] = callback ;
198
+ state -> callbacks [state -> ncallbacks ++ ] = callback ;
189
199
190
200
return Py_NewRef (func );
191
201
}
@@ -198,7 +208,8 @@ Run all registered exit functions.");
198
208
static PyObject *
199
209
atexit_run_exitfuncs (PyObject * module , PyObject * unused )
200
210
{
201
- atexit_callfuncs (module , 0 );
211
+ struct atexit_state * state = get_atexit_state ();
212
+ atexit_callfuncs (state , 0 );
202
213
if (PyErr_Occurred ()) {
203
214
return NULL ;
204
215
}
@@ -213,7 +224,7 @@ Clear the list of previously registered exit functions.");
213
224
static PyObject *
214
225
atexit_clear (PyObject * module , PyObject * unused )
215
226
{
216
- atexit_cleanup (get_atexit_state (module ));
227
+ atexit_cleanup (get_atexit_state ());
217
228
Py_RETURN_NONE ;
218
229
}
219
230
@@ -225,41 +236,10 @@ Return the number of registered exit functions.");
225
236
static PyObject *
226
237
atexit_ncallbacks (PyObject * module , PyObject * unused )
227
238
{
228
- struct atexit_state * state = get_atexit_state (module );
239
+ struct atexit_state * state = get_atexit_state ();
229
240
return PyLong_FromSsize_t (state -> ncallbacks );
230
241
}
231
242
232
- static int
233
- atexit_m_traverse (PyObject * module , visitproc visit , void * arg )
234
- {
235
- struct atexit_state * state = (struct atexit_state * )PyModule_GetState (module );
236
- for (int i = 0 ; i < state -> ncallbacks ; i ++ ) {
237
- atexit_callback * cb = state -> atexit_callbacks [i ];
238
- if (cb == NULL )
239
- continue ;
240
- Py_VISIT (cb -> func );
241
- Py_VISIT (cb -> args );
242
- Py_VISIT (cb -> kwargs );
243
- }
244
- return 0 ;
245
- }
246
-
247
- static int
248
- atexit_m_clear (PyObject * module )
249
- {
250
- struct atexit_state * state = (struct atexit_state * )PyModule_GetState (module );
251
- atexit_cleanup (state );
252
- return 0 ;
253
- }
254
-
255
- static void
256
- atexit_free (PyObject * module )
257
- {
258
- struct atexit_state * state = (struct atexit_state * )PyModule_GetState (module );
259
- atexit_cleanup (state );
260
- PyMem_Free (state -> atexit_callbacks );
261
- }
262
-
263
243
PyDoc_STRVAR (atexit_unregister__doc__ ,
264
244
"unregister(func) -> None\n\
265
245
\n\
@@ -271,10 +251,10 @@ atexit.register\n\
271
251
static PyObject *
272
252
atexit_unregister (PyObject * module , PyObject * func )
273
253
{
274
- struct atexit_state * state = get_atexit_state (module );
254
+ struct atexit_state * state = get_atexit_state ();
275
255
for (int i = 0 ; i < state -> ncallbacks ; i ++ )
276
256
{
277
- atexit_callback * cb = state -> atexit_callbacks [i ];
257
+ atexit_callback * cb = state -> callbacks [i ];
278
258
if (cb == NULL ) {
279
259
continue ;
280
260
}
@@ -305,6 +285,7 @@ static PyMethodDef atexit_methods[] = {
305
285
{NULL , NULL } /* sentinel */
306
286
};
307
287
288
+
308
289
/* ===================================================================== */
309
290
/* Initialization function. */
310
291
@@ -315,37 +296,12 @@ upon normal program termination.\n\
315
296
Two public functions, register and unregister, are defined.\n\
316
297
" );
317
298
318
- static int
319
- atexit_exec (PyObject * module )
320
- {
321
- struct atexit_state * state = get_atexit_state (module );
322
- state -> callback_len = 32 ;
323
- state -> ncallbacks = 0 ;
324
- state -> atexit_callbacks = PyMem_New (atexit_callback * , state -> callback_len );
325
- if (state -> atexit_callbacks == NULL ) {
326
- return -1 ;
327
- }
328
-
329
- PyInterpreterState * interp = _PyInterpreterState_GET ();
330
- interp -> atexit_module = module ;
331
- return 0 ;
332
- }
333
-
334
- static PyModuleDef_Slot atexit_slots [] = {
335
- {Py_mod_exec , atexit_exec },
336
- {0 , NULL }
337
- };
338
-
339
299
static struct PyModuleDef atexitmodule = {
340
300
PyModuleDef_HEAD_INIT ,
341
301
.m_name = "atexit" ,
342
302
.m_doc = atexit__doc__ ,
343
- .m_size = sizeof ( struct atexit_state ) ,
303
+ .m_size = 0 ,
344
304
.m_methods = atexit_methods ,
345
- .m_slots = atexit_slots ,
346
- .m_traverse = atexit_m_traverse ,
347
- .m_clear = atexit_m_clear ,
348
- .m_free = (freefunc )atexit_free
349
305
};
350
306
351
307
PyMODINIT_FUNC
0 commit comments