2 * atexit - allow programmer to define multiple exit functions to be executed
3 * upon normal program termination.
5 * Translated from atexit.py by Collin Winter.
6 + Copyright 2007 Python Software Foundation.
11 /* Forward declaration (for atexit_cleanup) */
12 static PyObject
*atexit_clear(PyObject
*);
14 /* ===================================================================== */
15 /* Callback machinery. */
23 static atexit_callback
**atexit_callbacks
;
24 static int ncallbacks
= 0;
25 static int callback_len
= 32;
27 /* Installed into pythonrun.c's atexit mechanism */
30 atexit_callfuncs(void)
32 PyObject
*exc_type
= NULL
, *exc_value
, *exc_tb
, *r
;
39 for (i
= ncallbacks
- 1; i
>= 0; i
--)
41 cb
= atexit_callbacks
[i
];
45 r
= PyObject_Call(cb
->func
, cb
->args
, cb
->kwargs
);
48 /* Maintain the last exception, but don't leak if there are
49 multiple exceptions. */
52 Py_XDECREF(exc_value
);
55 PyErr_Fetch(&exc_type
, &exc_value
, &exc_tb
);
56 if (!PyErr_ExceptionMatches(PyExc_SystemExit
)) {
57 PySys_WriteStderr("Error in atexit._run_exitfuncs:\n");
58 PyErr_Display(exc_type
, exc_value
, exc_tb
);
64 PyErr_Restore(exc_type
, exc_value
, exc_tb
);
68 atexit_delete_cb(int i
)
70 atexit_callback
*cb
= atexit_callbacks
[i
];
71 atexit_callbacks
[i
] = NULL
;
74 Py_XDECREF(cb
->kwargs
);
81 PyObject
*r
= atexit_clear(NULL
);
85 /* ===================================================================== */
88 PyDoc_STRVAR(atexit_register__doc__
,
89 "register(func, *args, **kwargs) -> func\n\
91 Register a function to be executed upon normal program termination\n\
93 func - function to be called at exit\n\
94 args - optional arguments to pass to func\n\
95 kwargs - optional keyword arguments to pass to func\n\
97 func is returned to facilitate usage as a decorator.");
100 atexit_register(PyObject
*self
, PyObject
*args
, PyObject
*kwargs
)
102 atexit_callback
*new_callback
;
103 PyObject
*func
= NULL
;
105 if (ncallbacks
>= callback_len
) {
108 r
= (atexit_callback
**)PyMem_Realloc(atexit_callbacks
,
109 sizeof(atexit_callback
*) * callback_len
);
111 return PyErr_NoMemory();
112 atexit_callbacks
= r
;
115 if (PyTuple_GET_SIZE(args
) == 0) {
116 PyErr_SetString(PyExc_TypeError
,
117 "register() takes at least 1 argument (0 given)");
121 func
= PyTuple_GET_ITEM(args
, 0);
122 if (!PyCallable_Check(func
)) {
123 PyErr_SetString(PyExc_TypeError
,
124 "the first argument must be callable");
128 new_callback
= PyMem_Malloc(sizeof(atexit_callback
));
129 if (new_callback
== NULL
)
130 return PyErr_NoMemory();
132 new_callback
->args
= PyTuple_GetSlice(args
, 1, PyTuple_GET_SIZE(args
));
133 if (new_callback
->args
== NULL
) {
134 PyMem_Free(new_callback
);
137 new_callback
->func
= func
;
138 new_callback
->kwargs
= kwargs
;
142 atexit_callbacks
[ncallbacks
++] = new_callback
;
148 PyDoc_STRVAR(atexit_run_exitfuncs__doc__
,
149 "_run_exitfuncs() -> None\n\
151 Run all registered exit functions.");
154 atexit_run_exitfuncs(PyObject
*self
)
157 if (PyErr_Occurred())
162 PyDoc_STRVAR(atexit_clear__doc__
,
165 Clear the list of previously registered exit functions.");
168 atexit_clear(PyObject
*self
)
173 for (i
= 0; i
< ncallbacks
; i
++)
175 cb
= atexit_callbacks
[i
];
185 PyDoc_STRVAR(atexit_unregister__doc__
,
186 "unregister(func) -> None\n\
188 Unregister a exit function which was previously registered using\n\
191 func - function to be unregistered");
194 atexit_unregister(PyObject
*self
, PyObject
*func
)
199 for (i
= 0; i
< ncallbacks
; i
++)
201 cb
= atexit_callbacks
[i
];
205 eq
= PyObject_RichCompareBool(cb
->func
, func
, Py_EQ
);
214 static PyMethodDef atexit_methods
[] = {
215 {"register", (PyCFunction
) atexit_register
, METH_VARARGS
|METH_KEYWORDS
,
216 atexit_register__doc__
},
217 {"_clear", (PyCFunction
) atexit_clear
, METH_NOARGS
,
218 atexit_clear__doc__
},
219 {"unregister", (PyCFunction
) atexit_unregister
, METH_O
,
220 atexit_unregister__doc__
},
221 {"_run_exitfuncs", (PyCFunction
) atexit_run_exitfuncs
, METH_NOARGS
,
222 atexit_run_exitfuncs__doc__
},
223 {NULL
, NULL
} /* sentinel */
226 /* ===================================================================== */
227 /* Initialization function. */
229 PyDoc_STRVAR(atexit__doc__
,
230 "allow programmer to define multiple exit functions to be executed\
231 upon normal program termination.\n\
233 Two public functions, register and unregister, are defined.\n\
241 atexit_callbacks
= PyMem_New(atexit_callback
*, callback_len
);
242 if (atexit_callbacks
== NULL
)
245 m
= Py_InitModule3("atexit", atexit_methods
, atexit__doc__
);
249 _Py_PyAtExit(atexit_callfuncs
);
250 /* Register a callback that will free
251 atexit_callbacks, otherwise valgrind will report memory leaks. */
252 Py_AtExit(atexit_cleanup
);