blob: 3cdf2d7e56348a75d99748272dc8bf7bcf59ded6 [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*);
Christian Heimes9c94ba42008-10-30 21:34:02 +000013/* Forward declaration of module object */
14static struct PyModuleDef atexitmodule;
Collin Winter3e81ec82007-03-23 22:46:49 +000015
Collin Winter670e6922007-03-21 02:57:17 +000016/* ===================================================================== */
17/* Callback machinery. */
18
19typedef struct {
20 PyObject *func;
21 PyObject *args;
22 PyObject *kwargs;
23} atexit_callback;
24
Christian Heimes9c94ba42008-10-30 21:34:02 +000025typedef struct {
26 atexit_callback **atexit_callbacks;
27 int ncallbacks;
28 int callback_len;
29} atexitmodule_state;
30
31#define GET_ATEXIT_STATE(mod) ((atexitmodule_state*)PyModule_GetState(mod))
32
Collin Winter670e6922007-03-21 02:57:17 +000033
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020034static void
35atexit_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 */
48static void
49atexit_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
Nick Coghland6009512014-11-20 21:39:37 +100063/* Installed into pylifecycle.c's atexit mechanism */
Collin Winter670e6922007-03-21 02:57:17 +000064
Skip Montanaro711552b2008-09-23 00:52:29 +000065static void
Collin Winter670e6922007-03-21 02:57:17 +000066atexit_callfuncs(void)
67{
68 PyObject *exc_type = NULL, *exc_value, *exc_tb, *r;
69 atexit_callback *cb;
Christian Heimes9c94ba42008-10-30 21:34:02 +000070 PyObject *module;
71 atexitmodule_state *modstate;
Collin Winter670e6922007-03-21 02:57:17 +000072 int i;
Christian Heimes9c94ba42008-10-30 21:34:02 +000073
74 module = PyState_FindModule(&atexitmodule);
75 if (module == NULL)
Collin Winter670e6922007-03-21 02:57:17 +000076 return;
Christian Heimes9c94ba42008-10-30 21:34:02 +000077 modstate = GET_ATEXIT_STATE(module);
78
79 if (modstate->ncallbacks == 0)
80 return;
81
82
83 for (i = modstate->ncallbacks - 1; i >= 0; i--)
Collin Winter670e6922007-03-21 02:57:17 +000084 {
Christian Heimes9c94ba42008-10-30 21:34:02 +000085 cb = modstate->atexit_callbacks[i];
Collin Winter670e6922007-03-21 02:57:17 +000086 if (cb == NULL)
87 continue;
88
89 r = PyObject_Call(cb->func, cb->args, cb->kwargs);
90 Py_XDECREF(r);
91 if (r == NULL) {
Neal Norwitz7d71fb82007-03-21 04:45:04 +000092 /* Maintain the last exception, but don't leak if there are
93 multiple exceptions. */
Collin Winter670e6922007-03-21 02:57:17 +000094 if (exc_type) {
95 Py_DECREF(exc_type);
Neal Norwitz7d71fb82007-03-21 04:45:04 +000096 Py_XDECREF(exc_value);
Serhiy Storchaka009b8112015-03-18 21:53:15 +020097 Py_XDECREF(exc_tb);
Collin Winter670e6922007-03-21 02:57:17 +000098 }
99 PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
100 if (!PyErr_ExceptionMatches(PyExc_SystemExit)) {
101 PySys_WriteStderr("Error in atexit._run_exitfuncs:\n");
Victor Stinner358e11d2011-01-05 03:54:25 +0000102 PyErr_NormalizeException(&exc_type, &exc_value, &exc_tb);
Collin Winter670e6922007-03-21 02:57:17 +0000103 PyErr_Display(exc_type, exc_value, exc_tb);
104 }
105 }
106 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000107
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200108 atexit_cleanup(modstate);
Skip Montanaro711552b2008-09-23 00:52:29 +0000109
Collin Winter670e6922007-03-21 02:57:17 +0000110 if (exc_type)
111 PyErr_Restore(exc_type, exc_value, exc_tb);
112}
113
Collin Winter670e6922007-03-21 02:57:17 +0000114/* ===================================================================== */
115/* Module methods. */
116
117PyDoc_STRVAR(atexit_register__doc__,
118"register(func, *args, **kwargs) -> func\n\
119\n\
120Register a function to be executed upon normal program termination\n\
121\n\
122 func - function to be called at exit\n\
123 args - optional arguments to pass to func\n\
124 kwargs - optional keyword arguments to pass to func\n\
125\n\
126 func is returned to facilitate usage as a decorator.");
127
128static PyObject *
129atexit_register(PyObject *self, PyObject *args, PyObject *kwargs)
130{
Christian Heimes9c94ba42008-10-30 21:34:02 +0000131 atexitmodule_state *modstate;
Collin Winter670e6922007-03-21 02:57:17 +0000132 atexit_callback *new_callback;
133 PyObject *func = NULL;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000134
135 modstate = GET_ATEXIT_STATE(self);
136
137 if (modstate->ncallbacks >= modstate->callback_len) {
Collin Winter3e81ec82007-03-23 22:46:49 +0000138 atexit_callback **r;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000139 modstate->callback_len += 16;
140 r = (atexit_callback**)PyMem_Realloc(modstate->atexit_callbacks,
141 sizeof(atexit_callback*) * modstate->callback_len);
Collin Winter3e81ec82007-03-23 22:46:49 +0000142 if (r == NULL)
143 return PyErr_NoMemory();
Christian Heimes9c94ba42008-10-30 21:34:02 +0000144 modstate->atexit_callbacks = r;
Collin Winter670e6922007-03-21 02:57:17 +0000145 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000146
Collin Winter670e6922007-03-21 02:57:17 +0000147 if (PyTuple_GET_SIZE(args) == 0) {
148 PyErr_SetString(PyExc_TypeError,
149 "register() takes at least 1 argument (0 given)");
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200150 return NULL;
Collin Winter670e6922007-03-21 02:57:17 +0000151 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000152
Collin Winter670e6922007-03-21 02:57:17 +0000153 func = PyTuple_GET_ITEM(args, 0);
154 if (!PyCallable_Check(func)) {
155 PyErr_SetString(PyExc_TypeError,
156 "the first argument must be callable");
157 return NULL;
158 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000159
Collin Winter670e6922007-03-21 02:57:17 +0000160 new_callback = PyMem_Malloc(sizeof(atexit_callback));
161 if (new_callback == NULL)
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200162 return PyErr_NoMemory();
Collin Winter670e6922007-03-21 02:57:17 +0000163
164 new_callback->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
165 if (new_callback->args == NULL) {
166 PyMem_Free(new_callback);
167 return NULL;
168 }
169 new_callback->func = func;
170 new_callback->kwargs = kwargs;
171 Py_INCREF(func);
172 Py_XINCREF(kwargs);
Christian Heimes9c94ba42008-10-30 21:34:02 +0000173
174 modstate->atexit_callbacks[modstate->ncallbacks++] = new_callback;
175
Collin Winter670e6922007-03-21 02:57:17 +0000176 Py_INCREF(func);
177 return func;
178}
179
Skip Montanaro28a181c2007-08-06 20:59:28 +0000180PyDoc_STRVAR(atexit_run_exitfuncs__doc__,
181"_run_exitfuncs() -> None\n\
182\n\
183Run all registered exit functions.");
184
Collin Winter670e6922007-03-21 02:57:17 +0000185static PyObject *
Christian Heimes9c94ba42008-10-30 21:34:02 +0000186atexit_run_exitfuncs(PyObject *self, PyObject *unused)
Collin Winter670e6922007-03-21 02:57:17 +0000187{
188 atexit_callfuncs();
189 if (PyErr_Occurred())
190 return NULL;
191 Py_RETURN_NONE;
192}
193
Skip Montanaro28a181c2007-08-06 20:59:28 +0000194PyDoc_STRVAR(atexit_clear__doc__,
195"_clear() -> None\n\
196\n\
197Clear the list of previously registered exit functions.");
198
Collin Winter670e6922007-03-21 02:57:17 +0000199static PyObject *
Christian Heimes9c94ba42008-10-30 21:34:02 +0000200atexit_clear(PyObject *self, PyObject *unused)
Collin Winter670e6922007-03-21 02:57:17 +0000201{
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200202 atexit_cleanup(GET_ATEXIT_STATE(self));
203 Py_RETURN_NONE;
204}
205
206PyDoc_STRVAR(atexit_ncallbacks__doc__,
207"_ncallbacks() -> int\n\
208\n\
209Return the number of registered exit functions.");
210
211static PyObject *
212atexit_ncallbacks(PyObject *self, PyObject *unused)
213{
Christian Heimes9c94ba42008-10-30 21:34:02 +0000214 atexitmodule_state *modstate;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000215
216 modstate = GET_ATEXIT_STATE(self);
217
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200218 return PyLong_FromSsize_t(modstate->ncallbacks);
219}
220
221static int
222atexit_m_traverse(PyObject *self, visitproc visit, void *arg)
223{
224 int i;
225 atexitmodule_state *modstate;
226
227 modstate = GET_ATEXIT_STATE(self);
Christian Heimes9c94ba42008-10-30 21:34:02 +0000228 for (i = 0; i < modstate->ncallbacks; i++) {
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200229 atexit_callback *cb = modstate->atexit_callbacks[i];
Collin Winter670e6922007-03-21 02:57:17 +0000230 if (cb == NULL)
231 continue;
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200232 Py_VISIT(cb->func);
233 Py_VISIT(cb->args);
234 Py_VISIT(cb->kwargs);
Collin Winter670e6922007-03-21 02:57:17 +0000235 }
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200236 return 0;
237}
238
239static int
240atexit_m_clear(PyObject *self)
241{
242 atexitmodule_state *modstate;
243 modstate = GET_ATEXIT_STATE(self);
244 atexit_cleanup(modstate);
245 return 0;
Collin Winter670e6922007-03-21 02:57:17 +0000246}
247
Stefan Krah650365b2012-03-27 11:49:21 +0200248static void
249atexit_free(PyObject *m)
250{
251 atexitmodule_state *modstate;
252 modstate = GET_ATEXIT_STATE(m);
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200253 atexit_cleanup(modstate);
Stefan Krah650365b2012-03-27 11:49:21 +0200254 PyMem_Free(modstate->atexit_callbacks);
255}
256
Skip Montanaro28a181c2007-08-06 20:59:28 +0000257PyDoc_STRVAR(atexit_unregister__doc__,
258"unregister(func) -> None\n\
259\n\
Martin Panter7462b6492015-11-02 03:37:02 +0000260Unregister an exit function which was previously registered using\n\
Skip Montanaro28a181c2007-08-06 20:59:28 +0000261atexit.register\n\
262\n\
263 func - function to be unregistered");
264
Collin Winter670e6922007-03-21 02:57:17 +0000265static PyObject *
266atexit_unregister(PyObject *self, PyObject *func)
267{
Christian Heimes9c94ba42008-10-30 21:34:02 +0000268 atexitmodule_state *modstate;
Collin Winter670e6922007-03-21 02:57:17 +0000269 atexit_callback *cb;
270 int i, eq;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000271
272 modstate = GET_ATEXIT_STATE(self);
273
274 for (i = 0; i < modstate->ncallbacks; i++)
Collin Winter670e6922007-03-21 02:57:17 +0000275 {
Christian Heimes9c94ba42008-10-30 21:34:02 +0000276 cb = modstate->atexit_callbacks[i];
Collin Winter670e6922007-03-21 02:57:17 +0000277 if (cb == NULL)
278 continue;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000279
Collin Winter670e6922007-03-21 02:57:17 +0000280 eq = PyObject_RichCompareBool(cb->func, func, Py_EQ);
281 if (eq < 0)
282 return NULL;
283 if (eq)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200284 atexit_delete_cb(modstate, i);
Collin Winter670e6922007-03-21 02:57:17 +0000285 }
286 Py_RETURN_NONE;
287}
288
289static PyMethodDef atexit_methods[] = {
290 {"register", (PyCFunction) atexit_register, METH_VARARGS|METH_KEYWORDS,
291 atexit_register__doc__},
292 {"_clear", (PyCFunction) atexit_clear, METH_NOARGS,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000293 atexit_clear__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000294 {"unregister", (PyCFunction) atexit_unregister, METH_O,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000295 atexit_unregister__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000296 {"_run_exitfuncs", (PyCFunction) atexit_run_exitfuncs, METH_NOARGS,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000297 atexit_run_exitfuncs__doc__},
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200298 {"_ncallbacks", (PyCFunction) atexit_ncallbacks, METH_NOARGS,
299 atexit_ncallbacks__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000300 {NULL, NULL} /* sentinel */
301};
302
303/* ===================================================================== */
304/* Initialization function. */
305
306PyDoc_STRVAR(atexit__doc__,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000307"allow programmer to define multiple exit functions to be executed\
Collin Winter670e6922007-03-21 02:57:17 +0000308upon normal program termination.\n\
309\n\
Skip Montanaro28a181c2007-08-06 20:59:28 +0000310Two public functions, register and unregister, are defined.\n\
Collin Winter670e6922007-03-21 02:57:17 +0000311");
312
Martin v. Löwis1a214512008-06-11 05:26:20 +0000313
314static struct PyModuleDef atexitmodule = {
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200315 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
Martin v. Löwis1a214512008-06-11 05:26:20 +0000324};
325
Collin Winter670e6922007-03-21 02:57:17 +0000326PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000327PyInit_atexit(void)
Collin Winter670e6922007-03-21 02:57:17 +0000328{
329 PyObject *m;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000330 atexitmodule_state *modstate;
Collin Winter670e6922007-03-21 02:57:17 +0000331
Martin v. Löwis1a214512008-06-11 05:26:20 +0000332 m = PyModule_Create(&atexitmodule);
Collin Winter670e6922007-03-21 02:57:17 +0000333 if (m == NULL)
Martin v. Löwis1a214512008-06-11 05:26:20 +0000334 return NULL;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000335
336 modstate = GET_ATEXIT_STATE(m);
337 modstate->callback_len = 32;
338 modstate->ncallbacks = 0;
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200339 modstate->atexit_callbacks = PyMem_New(atexit_callback*,
Christian Heimes9c94ba42008-10-30 21:34:02 +0000340 modstate->callback_len);
341 if (modstate->atexit_callbacks == NULL)
342 return NULL;
343
Collin Winter670e6922007-03-21 02:57:17 +0000344 _Py_PyAtExit(atexit_callfuncs);
Martin v. Löwis1a214512008-06-11 05:26:20 +0000345 return m;
Collin Winter670e6922007-03-21 02:57:17 +0000346}