blob: f68d8047ed7ee88f89fb98642893b98dedff1cf7 [file] [log] [blame]
Collin Winter670e6922007-03-21 02:57:17 +00001/*
2 * atexit - allow programmer to define multiple exit functions to be executed
3 * upon normal program termination.
4 *
5 * Translated from atexit.py by Collin Winter.
6 + Copyright 2007 Python Software Foundation.
7 */
8
9#include "Python.h"
10
Collin Winter3e81ec82007-03-23 22:46:49 +000011/* Forward declaration (for atexit_cleanup) */
Christian Heimes9c94ba42008-10-30 21:34:02 +000012static PyObject *atexit_clear(PyObject*, PyObject*);
Skip Montanaro711552b2008-09-23 00:52:29 +000013/* Forward declaration (for atexit_callfuncs) */
Christian Heimes9c94ba42008-10-30 21:34:02 +000014static void atexit_cleanup(PyObject*);
15/* Forward declaration of module object */
16static struct PyModuleDef atexitmodule;
Collin Winter3e81ec82007-03-23 22:46:49 +000017
Collin Winter670e6922007-03-21 02:57:17 +000018/* ===================================================================== */
19/* Callback machinery. */
20
21typedef struct {
22 PyObject *func;
23 PyObject *args;
24 PyObject *kwargs;
25} atexit_callback;
26
Christian Heimes9c94ba42008-10-30 21:34:02 +000027typedef 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
Collin Winter670e6922007-03-21 02:57:17 +000035
36/* Installed into pythonrun.c's atexit mechanism */
37
Skip Montanaro711552b2008-09-23 00:52:29 +000038static void
Collin Winter670e6922007-03-21 02:57:17 +000039atexit_callfuncs(void)
40{
41 PyObject *exc_type = NULL, *exc_value, *exc_tb, *r;
42 atexit_callback *cb;
Christian Heimes9c94ba42008-10-30 21:34:02 +000043 PyObject *module;
44 atexitmodule_state *modstate;
Collin Winter670e6922007-03-21 02:57:17 +000045 int i;
Christian Heimes9c94ba42008-10-30 21:34:02 +000046
47 module = PyState_FindModule(&atexitmodule);
48 if (module == NULL)
Collin Winter670e6922007-03-21 02:57:17 +000049 return;
Christian Heimes9c94ba42008-10-30 21:34:02 +000050 modstate = GET_ATEXIT_STATE(module);
51
52 if (modstate->ncallbacks == 0)
53 return;
54
55
56 for (i = modstate->ncallbacks - 1; i >= 0; i--)
Collin Winter670e6922007-03-21 02:57:17 +000057 {
Christian Heimes9c94ba42008-10-30 21:34:02 +000058 cb = modstate->atexit_callbacks[i];
Collin Winter670e6922007-03-21 02:57:17 +000059 if (cb == NULL)
60 continue;
61
62 r = PyObject_Call(cb->func, cb->args, cb->kwargs);
63 Py_XDECREF(r);
64 if (r == NULL) {
Neal Norwitz7d71fb82007-03-21 04:45:04 +000065 /* Maintain the last exception, but don't leak if there are
66 multiple exceptions. */
Collin Winter670e6922007-03-21 02:57:17 +000067 if (exc_type) {
68 Py_DECREF(exc_type);
Neal Norwitz7d71fb82007-03-21 04:45:04 +000069 Py_XDECREF(exc_value);
70 Py_XDECREF(exc_tb);
Collin Winter670e6922007-03-21 02:57:17 +000071 }
72 PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
73 if (!PyErr_ExceptionMatches(PyExc_SystemExit)) {
74 PySys_WriteStderr("Error in atexit._run_exitfuncs:\n");
Victor Stinner358e11d2011-01-05 03:54:25 +000075 PyErr_NormalizeException(&exc_type, &exc_value, &exc_tb);
Collin Winter670e6922007-03-21 02:57:17 +000076 PyErr_Display(exc_type, exc_value, exc_tb);
77 }
78 }
79 }
Christian Heimes9c94ba42008-10-30 21:34:02 +000080
81 atexit_cleanup(module);
Skip Montanaro711552b2008-09-23 00:52:29 +000082
Collin Winter670e6922007-03-21 02:57:17 +000083 if (exc_type)
84 PyErr_Restore(exc_type, exc_value, exc_tb);
85}
86
Skip Montanaro711552b2008-09-23 00:52:29 +000087static void
Christian Heimes9c94ba42008-10-30 21:34:02 +000088atexit_delete_cb(PyObject *self, int i)
Collin Winter670e6922007-03-21 02:57:17 +000089{
Christian Heimes9c94ba42008-10-30 21:34:02 +000090 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;
Collin Winter670e6922007-03-21 02:57:17 +000096 Py_DECREF(cb->func);
97 Py_DECREF(cb->args);
98 Py_XDECREF(cb->kwargs);
Christian Heimes9c94ba42008-10-30 21:34:02 +000099 PyMem_Free(cb);
Collin Winter670e6922007-03-21 02:57:17 +0000100}
101
Skip Montanaro711552b2008-09-23 00:52:29 +0000102static void
Christian Heimes9c94ba42008-10-30 21:34:02 +0000103atexit_cleanup(PyObject *self)
Collin Winter3e81ec82007-03-23 22:46:49 +0000104{
Christian Heimes9c94ba42008-10-30 21:34:02 +0000105 PyObject *r = atexit_clear(self, NULL);
Collin Winter3e81ec82007-03-23 22:46:49 +0000106 Py_DECREF(r);
107}
108
Collin Winter670e6922007-03-21 02:57:17 +0000109/* ===================================================================== */
110/* Module methods. */
111
112PyDoc_STRVAR(atexit_register__doc__,
113"register(func, *args, **kwargs) -> func\n\
114\n\
115Register a function to be executed upon normal program termination\n\
116\n\
117 func - function to be called at exit\n\
118 args - optional arguments to pass to func\n\
119 kwargs - optional keyword arguments to pass to func\n\
120\n\
121 func is returned to facilitate usage as a decorator.");
122
123static PyObject *
124atexit_register(PyObject *self, PyObject *args, PyObject *kwargs)
125{
Christian Heimes9c94ba42008-10-30 21:34:02 +0000126 atexitmodule_state *modstate;
Collin Winter670e6922007-03-21 02:57:17 +0000127 atexit_callback *new_callback;
128 PyObject *func = NULL;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000129
130 modstate = GET_ATEXIT_STATE(self);
131
132 if (modstate->ncallbacks >= modstate->callback_len) {
Collin Winter3e81ec82007-03-23 22:46:49 +0000133 atexit_callback **r;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000134 modstate->callback_len += 16;
135 r = (atexit_callback**)PyMem_Realloc(modstate->atexit_callbacks,
136 sizeof(atexit_callback*) * modstate->callback_len);
Collin Winter3e81ec82007-03-23 22:46:49 +0000137 if (r == NULL)
138 return PyErr_NoMemory();
Christian Heimes9c94ba42008-10-30 21:34:02 +0000139 modstate->atexit_callbacks = r;
Collin Winter670e6922007-03-21 02:57:17 +0000140 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000141
Collin Winter670e6922007-03-21 02:57:17 +0000142 if (PyTuple_GET_SIZE(args) == 0) {
143 PyErr_SetString(PyExc_TypeError,
144 "register() takes at least 1 argument (0 given)");
145 return NULL;
146 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000147
Collin Winter670e6922007-03-21 02:57:17 +0000148 func = PyTuple_GET_ITEM(args, 0);
149 if (!PyCallable_Check(func)) {
150 PyErr_SetString(PyExc_TypeError,
151 "the first argument must be callable");
152 return NULL;
153 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000154
Collin Winter670e6922007-03-21 02:57:17 +0000155 new_callback = PyMem_Malloc(sizeof(atexit_callback));
156 if (new_callback == NULL)
157 return PyErr_NoMemory();
158
159 new_callback->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
160 if (new_callback->args == NULL) {
161 PyMem_Free(new_callback);
162 return NULL;
163 }
164 new_callback->func = func;
165 new_callback->kwargs = kwargs;
166 Py_INCREF(func);
167 Py_XINCREF(kwargs);
Christian Heimes9c94ba42008-10-30 21:34:02 +0000168
169 modstate->atexit_callbacks[modstate->ncallbacks++] = new_callback;
170
Collin Winter670e6922007-03-21 02:57:17 +0000171 Py_INCREF(func);
172 return func;
173}
174
Skip Montanaro28a181c2007-08-06 20:59:28 +0000175PyDoc_STRVAR(atexit_run_exitfuncs__doc__,
176"_run_exitfuncs() -> None\n\
177\n\
178Run all registered exit functions.");
179
Collin Winter670e6922007-03-21 02:57:17 +0000180static PyObject *
Christian Heimes9c94ba42008-10-30 21:34:02 +0000181atexit_run_exitfuncs(PyObject *self, PyObject *unused)
Collin Winter670e6922007-03-21 02:57:17 +0000182{
183 atexit_callfuncs();
184 if (PyErr_Occurred())
185 return NULL;
186 Py_RETURN_NONE;
187}
188
Skip Montanaro28a181c2007-08-06 20:59:28 +0000189PyDoc_STRVAR(atexit_clear__doc__,
190"_clear() -> None\n\
191\n\
192Clear the list of previously registered exit functions.");
193
Collin Winter670e6922007-03-21 02:57:17 +0000194static PyObject *
Christian Heimes9c94ba42008-10-30 21:34:02 +0000195atexit_clear(PyObject *self, PyObject *unused)
Collin Winter670e6922007-03-21 02:57:17 +0000196{
Christian Heimes9c94ba42008-10-30 21:34:02 +0000197 atexitmodule_state *modstate;
Collin Winter670e6922007-03-21 02:57:17 +0000198 atexit_callback *cb;
199 int i;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000200
201 modstate = GET_ATEXIT_STATE(self);
202
203 for (i = 0; i < modstate->ncallbacks; i++) {
204 cb = modstate->atexit_callbacks[i];
Collin Winter670e6922007-03-21 02:57:17 +0000205 if (cb == NULL)
206 continue;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000207
208 atexit_delete_cb(self, i);
Collin Winter670e6922007-03-21 02:57:17 +0000209 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000210 modstate->ncallbacks = 0;
Collin Winter670e6922007-03-21 02:57:17 +0000211 Py_RETURN_NONE;
212}
213
Stefan Krah650365b2012-03-27 11:49:21 +0200214static void
215atexit_free(PyObject *m)
216{
217 atexitmodule_state *modstate;
218 modstate = GET_ATEXIT_STATE(m);
219 PyMem_Free(modstate->atexit_callbacks);
220}
221
Skip Montanaro28a181c2007-08-06 20:59:28 +0000222PyDoc_STRVAR(atexit_unregister__doc__,
223"unregister(func) -> None\n\
224\n\
225Unregister a exit function which was previously registered using\n\
226atexit.register\n\
227\n\
228 func - function to be unregistered");
229
Collin Winter670e6922007-03-21 02:57:17 +0000230static PyObject *
231atexit_unregister(PyObject *self, PyObject *func)
232{
Christian Heimes9c94ba42008-10-30 21:34:02 +0000233 atexitmodule_state *modstate;
Collin Winter670e6922007-03-21 02:57:17 +0000234 atexit_callback *cb;
235 int i, eq;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000236
237 modstate = GET_ATEXIT_STATE(self);
238
239 for (i = 0; i < modstate->ncallbacks; i++)
Collin Winter670e6922007-03-21 02:57:17 +0000240 {
Christian Heimes9c94ba42008-10-30 21:34:02 +0000241 cb = modstate->atexit_callbacks[i];
Collin Winter670e6922007-03-21 02:57:17 +0000242 if (cb == NULL)
243 continue;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000244
Collin Winter670e6922007-03-21 02:57:17 +0000245 eq = PyObject_RichCompareBool(cb->func, func, Py_EQ);
246 if (eq < 0)
247 return NULL;
248 if (eq)
Christian Heimes9c94ba42008-10-30 21:34:02 +0000249 atexit_delete_cb(self, i);
Collin Winter670e6922007-03-21 02:57:17 +0000250 }
251 Py_RETURN_NONE;
252}
253
254static PyMethodDef atexit_methods[] = {
255 {"register", (PyCFunction) atexit_register, METH_VARARGS|METH_KEYWORDS,
256 atexit_register__doc__},
257 {"_clear", (PyCFunction) atexit_clear, METH_NOARGS,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000258 atexit_clear__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000259 {"unregister", (PyCFunction) atexit_unregister, METH_O,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000260 atexit_unregister__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000261 {"_run_exitfuncs", (PyCFunction) atexit_run_exitfuncs, METH_NOARGS,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000262 atexit_run_exitfuncs__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000263 {NULL, NULL} /* sentinel */
264};
265
266/* ===================================================================== */
267/* Initialization function. */
268
269PyDoc_STRVAR(atexit__doc__,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000270"allow programmer to define multiple exit functions to be executed\
Collin Winter670e6922007-03-21 02:57:17 +0000271upon normal program termination.\n\
272\n\
Skip Montanaro28a181c2007-08-06 20:59:28 +0000273Two public functions, register and unregister, are defined.\n\
Collin Winter670e6922007-03-21 02:57:17 +0000274");
275
Martin v. Löwis1a214512008-06-11 05:26:20 +0000276
277static struct PyModuleDef atexitmodule = {
278 PyModuleDef_HEAD_INIT,
279 "atexit",
280 atexit__doc__,
Christian Heimes9c94ba42008-10-30 21:34:02 +0000281 sizeof(atexitmodule_state),
Martin v. Löwis1a214512008-06-11 05:26:20 +0000282 atexit_methods,
283 NULL,
284 NULL,
285 NULL,
Stefan Krah650365b2012-03-27 11:49:21 +0200286 (freefunc)atexit_free
Martin v. Löwis1a214512008-06-11 05:26:20 +0000287};
288
Collin Winter670e6922007-03-21 02:57:17 +0000289PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000290PyInit_atexit(void)
Collin Winter670e6922007-03-21 02:57:17 +0000291{
292 PyObject *m;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000293 atexitmodule_state *modstate;
Collin Winter670e6922007-03-21 02:57:17 +0000294
Martin v. Löwis1a214512008-06-11 05:26:20 +0000295 m = PyModule_Create(&atexitmodule);
Collin Winter670e6922007-03-21 02:57:17 +0000296 if (m == NULL)
Martin v. Löwis1a214512008-06-11 05:26:20 +0000297 return NULL;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000298
299 modstate = GET_ATEXIT_STATE(m);
300 modstate->callback_len = 32;
301 modstate->ncallbacks = 0;
302 modstate->atexit_callbacks = PyMem_New(atexit_callback*,
303 modstate->callback_len);
304 if (modstate->atexit_callbacks == NULL)
305 return NULL;
306
Collin Winter670e6922007-03-21 02:57:17 +0000307 _Py_PyAtExit(atexit_callfuncs);
Martin v. Löwis1a214512008-06-11 05:26:20 +0000308 return m;
Collin Winter670e6922007-03-21 02:57:17 +0000309}