10
10
11
11
/* Forward declaration (for atexit_cleanup) */
12
12
static PyObject * atexit_clear (PyObject * , PyObject * );
13
- /* Forward declaration (for atexit_callfuncs) */
14
- static void atexit_cleanup (PyObject * );
15
13
/* Forward declaration of module object */
16
14
static struct PyModuleDef atexitmodule ;
17
15
@@ -33,6 +31,35 @@ typedef struct {
33
31
#define GET_ATEXIT_STATE (mod ) ((atexitmodule_state*)PyModule_GetState(mod))
34
32
35
33
34
+ static void
35
+ atexit_delete_cb (atexitmodule_state * modstate , int i )
36
+ {
37
+ atexit_callback * cb ;
38
+
39
+ cb = modstate -> atexit_callbacks [i ];
40
+ modstate -> atexit_callbacks [i ] = NULL ;
41
+ Py_DECREF (cb -> func );
42
+ Py_DECREF (cb -> args );
43
+ Py_XDECREF (cb -> kwargs );
44
+ PyMem_Free (cb );
45
+ }
46
+
47
+ /* Clear all callbacks without calling them */
48
+ static void
49
+ atexit_cleanup (atexitmodule_state * modstate )
50
+ {
51
+ atexit_callback * cb ;
52
+ int i ;
53
+ for (i = 0 ; i < modstate -> ncallbacks ; i ++ ) {
54
+ cb = modstate -> atexit_callbacks [i ];
55
+ if (cb == NULL )
56
+ continue ;
57
+
58
+ atexit_delete_cb (modstate , i );
59
+ }
60
+ modstate -> ncallbacks = 0 ;
61
+ }
62
+
36
63
/* Installed into pythonrun.c's atexit mechanism */
37
64
38
65
static void
@@ -78,34 +105,12 @@ atexit_callfuncs(void)
78
105
}
79
106
}
80
107
81
- atexit_cleanup (module );
108
+ atexit_cleanup (modstate );
82
109
83
110
if (exc_type )
84
111
PyErr_Restore (exc_type , exc_value , exc_tb );
85
112
}
86
113
87
- static void
88
- atexit_delete_cb (PyObject * self , int i )
89
- {
90
- atexitmodule_state * modstate ;
91
- atexit_callback * cb ;
92
-
93
- modstate = GET_ATEXIT_STATE (self );
94
- cb = modstate -> atexit_callbacks [i ];
95
- modstate -> atexit_callbacks [i ] = NULL ;
96
- Py_DECREF (cb -> func );
97
- Py_DECREF (cb -> args );
98
- Py_XDECREF (cb -> kwargs );
99
- PyMem_Free (cb );
100
- }
101
-
102
- static void
103
- atexit_cleanup (PyObject * self )
104
- {
105
- PyObject * r = atexit_clear (self , NULL );
106
- Py_DECREF (r );
107
- }
108
-
109
114
/* ===================================================================== */
110
115
/* Module methods. */
111
116
@@ -193,29 +198,59 @@ Clear the list of previously registered exit functions.");
193
198
194
199
static PyObject *
195
200
atexit_clear (PyObject * self , PyObject * unused )
201
+ {
202
+ atexit_cleanup (GET_ATEXIT_STATE (self ));
203
+ Py_RETURN_NONE ;
204
+ }
205
+
206
+ PyDoc_STRVAR (atexit_ncallbacks__doc__ ,
207
+ "_ncallbacks() -> int\n\
208
+ \n\
209
+ Return the number of registered exit functions." );
210
+
211
+ static PyObject *
212
+ atexit_ncallbacks (PyObject * self , PyObject * unused )
196
213
{
197
214
atexitmodule_state * modstate ;
198
- atexit_callback * cb ;
199
- int i ;
200
215
201
216
modstate = GET_ATEXIT_STATE (self );
202
217
218
+ return PyLong_FromSsize_t (modstate -> ncallbacks );
219
+ }
220
+
221
+ static int
222
+ atexit_m_traverse (PyObject * self , visitproc visit , void * arg )
223
+ {
224
+ int i ;
225
+ atexitmodule_state * modstate ;
226
+
227
+ modstate = GET_ATEXIT_STATE (self );
203
228
for (i = 0 ; i < modstate -> ncallbacks ; i ++ ) {
204
- cb = modstate -> atexit_callbacks [i ];
229
+ atexit_callback * cb = modstate -> atexit_callbacks [i ];
205
230
if (cb == NULL )
206
231
continue ;
207
-
208
- atexit_delete_cb (self , i );
232
+ Py_VISIT (cb -> func );
233
+ Py_VISIT (cb -> args );
234
+ Py_VISIT (cb -> kwargs );
209
235
}
210
- modstate -> ncallbacks = 0 ;
211
- Py_RETURN_NONE ;
236
+ return 0 ;
237
+ }
238
+
239
+ static int
240
+ atexit_m_clear (PyObject * self )
241
+ {
242
+ atexitmodule_state * modstate ;
243
+ modstate = GET_ATEXIT_STATE (self );
244
+ atexit_cleanup (modstate );
245
+ return 0 ;
212
246
}
213
247
214
248
static void
215
249
atexit_free (PyObject * m )
216
250
{
217
251
atexitmodule_state * modstate ;
218
252
modstate = GET_ATEXIT_STATE (m );
253
+ atexit_cleanup (modstate );
219
254
PyMem_Free (modstate -> atexit_callbacks );
220
255
}
221
256
@@ -246,7 +281,7 @@ atexit_unregister(PyObject *self, PyObject *func)
246
281
if (eq < 0 )
247
282
return NULL ;
248
283
if (eq )
249
- atexit_delete_cb (self , i );
284
+ atexit_delete_cb (modstate , i );
250
285
}
251
286
Py_RETURN_NONE ;
252
287
}
@@ -260,6 +295,8 @@ static PyMethodDef atexit_methods[] = {
260
295
atexit_unregister__doc__ },
261
296
{"_run_exitfuncs" , (PyCFunction ) atexit_run_exitfuncs , METH_NOARGS ,
262
297
atexit_run_exitfuncs__doc__ },
298
+ {"_ncallbacks" , (PyCFunction ) atexit_ncallbacks , METH_NOARGS ,
299
+ atexit_ncallbacks__doc__ },
263
300
{NULL , NULL } /* sentinel */
264
301
};
265
302
@@ -275,15 +312,15 @@ Two public functions, register and unregister, are defined.\n\
275
312
276
313
277
314
static struct PyModuleDef atexitmodule = {
278
- PyModuleDef_HEAD_INIT ,
279
- "atexit" ,
280
- atexit__doc__ ,
281
- sizeof (atexitmodule_state ),
282
- atexit_methods ,
283
- NULL ,
284
- NULL ,
285
- NULL ,
286
- (freefunc )atexit_free
315
+ PyModuleDef_HEAD_INIT ,
316
+ "atexit" ,
317
+ atexit__doc__ ,
318
+ sizeof (atexitmodule_state ),
319
+ atexit_methods ,
320
+ NULL ,
321
+ atexit_m_traverse ,
322
+ atexit_m_clear ,
323
+ (freefunc )atexit_free
287
324
};
288
325
289
326
PyMODINIT_FUNC
0 commit comments