blob: 90ed7d50cad492eecda7fb464f19041fc943e2c6 [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"
Victor Stinner83d52042020-12-14 22:40:40 +010010#include "pycore_interp.h" // PyInterpreterState.atexit_func
11#include "pycore_pystate.h" // _PyInterpreterState_GET
Collin Winter3e81ec82007-03-23 22:46:49 +000012
Collin Winter670e6922007-03-21 02:57:17 +000013/* ===================================================================== */
14/* Callback machinery. */
15
16typedef struct {
17 PyObject *func;
18 PyObject *args;
19 PyObject *kwargs;
20} atexit_callback;
21
Victor Stinner83d52042020-12-14 22:40:40 +010022struct atexit_state {
Christian Heimes9c94ba42008-10-30 21:34:02 +000023 atexit_callback **atexit_callbacks;
24 int ncallbacks;
25 int callback_len;
Victor Stinner83d52042020-12-14 22:40:40 +010026};
Christian Heimes9c94ba42008-10-30 21:34:02 +000027
Victor Stinner83d52042020-12-14 22:40:40 +010028static inline struct atexit_state*
Hai Shif707d942020-03-16 21:15:01 +080029get_atexit_state(PyObject *module)
30{
31 void *state = PyModule_GetState(module);
32 assert(state != NULL);
Victor Stinner83d52042020-12-14 22:40:40 +010033 return (struct atexit_state *)state;
Hai Shif707d942020-03-16 21:15:01 +080034}
Christian Heimes9c94ba42008-10-30 21:34:02 +000035
Collin Winter670e6922007-03-21 02:57:17 +000036
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020037static void
Victor Stinner83d52042020-12-14 22:40:40 +010038atexit_delete_cb(struct atexit_state *state, int i)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020039{
Victor Stinner83d52042020-12-14 22:40:40 +010040 atexit_callback *cb = state->atexit_callbacks[i];
41 state->atexit_callbacks[i] = NULL;
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020042
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020043 Py_DECREF(cb->func);
44 Py_DECREF(cb->args);
45 Py_XDECREF(cb->kwargs);
46 PyMem_Free(cb);
47}
48
Victor Stinner83d52042020-12-14 22:40:40 +010049
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020050/* Clear all callbacks without calling them */
51static void
Victor Stinner83d52042020-12-14 22:40:40 +010052atexit_cleanup(struct atexit_state *state)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020053{
54 atexit_callback *cb;
Victor Stinner83d52042020-12-14 22:40:40 +010055 for (int i = 0; i < state->ncallbacks; i++) {
56 cb = state->atexit_callbacks[i];
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020057 if (cb == NULL)
58 continue;
59
Victor Stinner83d52042020-12-14 22:40:40 +010060 atexit_delete_cb(state, i);
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020061 }
Victor Stinner83d52042020-12-14 22:40:40 +010062 state->ncallbacks = 0;
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020063}
64
Nick Coghland6009512014-11-20 21:39:37 +100065/* Installed into pylifecycle.c's atexit mechanism */
Collin Winter670e6922007-03-21 02:57:17 +000066
Skip Montanaro711552b2008-09-23 00:52:29 +000067static void
Victor Stinner357704c2020-12-14 23:07:54 +010068atexit_callfuncs(PyObject *module, int ignore_exc)
Collin Winter670e6922007-03-21 02:57:17 +000069{
Victor Stinner83d52042020-12-14 22:40:40 +010070 assert(!PyErr_Occurred());
Christian Heimes9c94ba42008-10-30 21:34:02 +000071
Victor Stinner83d52042020-12-14 22:40:40 +010072 if (module == NULL) {
Collin Winter670e6922007-03-21 02:57:17 +000073 return;
Victor Stinner83d52042020-12-14 22:40:40 +010074 }
Christian Heimes9c94ba42008-10-30 21:34:02 +000075
Victor Stinner83d52042020-12-14 22:40:40 +010076 struct atexit_state *state = get_atexit_state(module);
77 if (state->ncallbacks == 0) {
Christian Heimes9c94ba42008-10-30 21:34:02 +000078 return;
Victor Stinner83d52042020-12-14 22:40:40 +010079 }
Christian Heimes9c94ba42008-10-30 21:34:02 +000080
Victor Stinner83d52042020-12-14 22:40:40 +010081 PyObject *exc_type = NULL, *exc_value, *exc_tb;
82 for (int i = state->ncallbacks - 1; i >= 0; i--) {
83 atexit_callback *cb = state->atexit_callbacks[i];
84 if (cb == NULL) {
Collin Winter670e6922007-03-21 02:57:17 +000085 continue;
Victor Stinner83d52042020-12-14 22:40:40 +010086 }
Collin Winter670e6922007-03-21 02:57:17 +000087
Victor Stinner83d52042020-12-14 22:40:40 +010088 PyObject *res = PyObject_Call(cb->func, cb->args, cb->kwargs);
89 if (res == NULL) {
Victor Stinner357704c2020-12-14 23:07:54 +010090 if (ignore_exc) {
91 _PyErr_WriteUnraisableMsg("in atexit callback", cb->func);
Collin Winter670e6922007-03-21 02:57:17 +000092 }
Victor Stinner357704c2020-12-14 23:07:54 +010093 else {
94 /* Maintain the last exception, but don't leak if there are
95 multiple exceptions. */
96 if (exc_type) {
97 Py_DECREF(exc_type);
98 Py_XDECREF(exc_value);
99 Py_XDECREF(exc_tb);
100 }
101 PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
102 if (!PyErr_GivenExceptionMatches(exc_type, PyExc_SystemExit)) {
103 PySys_WriteStderr("Error in atexit._run_exitfuncs:\n");
104 PyErr_NormalizeException(&exc_type, &exc_value, &exc_tb);
105 PyErr_Display(exc_type, exc_value, exc_tb);
106 }
Collin Winter670e6922007-03-21 02:57:17 +0000107 }
108 }
Victor Stinner83d52042020-12-14 22:40:40 +0100109 else {
110 Py_DECREF(res);
111 }
Collin Winter670e6922007-03-21 02:57:17 +0000112 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000113
Victor Stinner83d52042020-12-14 22:40:40 +0100114 atexit_cleanup(state);
Skip Montanaro711552b2008-09-23 00:52:29 +0000115
Victor Stinner357704c2020-12-14 23:07:54 +0100116 if (ignore_exc) {
117 assert(!PyErr_Occurred());
118 }
119 else {
120 if (exc_type) {
121 PyErr_Restore(exc_type, exc_value, exc_tb);
122 }
Victor Stinner83d52042020-12-14 22:40:40 +0100123 }
Collin Winter670e6922007-03-21 02:57:17 +0000124}
125
Victor Stinner357704c2020-12-14 23:07:54 +0100126
127void
128_PyAtExit_Call(PyObject *module)
129{
130 atexit_callfuncs(module, 1);
131}
132
133
Collin Winter670e6922007-03-21 02:57:17 +0000134/* ===================================================================== */
135/* Module methods. */
136
137PyDoc_STRVAR(atexit_register__doc__,
138"register(func, *args, **kwargs) -> func\n\
139\n\
140Register a function to be executed upon normal program termination\n\
141\n\
142 func - function to be called at exit\n\
143 args - optional arguments to pass to func\n\
144 kwargs - optional keyword arguments to pass to func\n\
145\n\
146 func is returned to facilitate usage as a decorator.");
147
148static PyObject *
Victor Stinner83d52042020-12-14 22:40:40 +0100149atexit_register(PyObject *module, PyObject *args, PyObject *kwargs)
Collin Winter670e6922007-03-21 02:57:17 +0000150{
Collin Winter670e6922007-03-21 02:57:17 +0000151 if (PyTuple_GET_SIZE(args) == 0) {
152 PyErr_SetString(PyExc_TypeError,
153 "register() takes at least 1 argument (0 given)");
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200154 return NULL;
Collin Winter670e6922007-03-21 02:57:17 +0000155 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000156
Victor Stinner83d52042020-12-14 22:40:40 +0100157 PyObject *func = PyTuple_GET_ITEM(args, 0);
Collin Winter670e6922007-03-21 02:57:17 +0000158 if (!PyCallable_Check(func)) {
159 PyErr_SetString(PyExc_TypeError,
160 "the first argument must be callable");
161 return NULL;
162 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000163
Victor Stinner83d52042020-12-14 22:40:40 +0100164 struct atexit_state *state = get_atexit_state(module);
165 if (state->ncallbacks >= state->callback_len) {
166 atexit_callback **r;
167 state->callback_len += 16;
168 r = (atexit_callback**)PyMem_Realloc(state->atexit_callbacks,
169 sizeof(atexit_callback*) * state->callback_len);
170 if (r == NULL)
171 return PyErr_NoMemory();
172 state->atexit_callbacks = r;
173 }
Collin Winter670e6922007-03-21 02:57:17 +0000174
Victor Stinner83d52042020-12-14 22:40:40 +0100175 atexit_callback *callback = PyMem_Malloc(sizeof(atexit_callback));
176 if (callback == NULL) {
177 return PyErr_NoMemory();
178 }
179
180 callback->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
181 if (callback->args == NULL) {
182 PyMem_Free(callback);
Collin Winter670e6922007-03-21 02:57:17 +0000183 return NULL;
184 }
Victor Stinner83d52042020-12-14 22:40:40 +0100185 callback->func = Py_NewRef(func);
186 callback->kwargs = Py_XNewRef(kwargs);
Christian Heimes9c94ba42008-10-30 21:34:02 +0000187
Victor Stinner83d52042020-12-14 22:40:40 +0100188 state->atexit_callbacks[state->ncallbacks++] = callback;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000189
Victor Stinner83d52042020-12-14 22:40:40 +0100190 return Py_NewRef(func);
Collin Winter670e6922007-03-21 02:57:17 +0000191}
192
Skip Montanaro28a181c2007-08-06 20:59:28 +0000193PyDoc_STRVAR(atexit_run_exitfuncs__doc__,
194"_run_exitfuncs() -> None\n\
195\n\
196Run all registered exit functions.");
197
Collin Winter670e6922007-03-21 02:57:17 +0000198static PyObject *
Victor Stinner83d52042020-12-14 22:40:40 +0100199atexit_run_exitfuncs(PyObject *module, PyObject *unused)
Collin Winter670e6922007-03-21 02:57:17 +0000200{
Victor Stinner357704c2020-12-14 23:07:54 +0100201 atexit_callfuncs(module, 0);
Victor Stinner83d52042020-12-14 22:40:40 +0100202 if (PyErr_Occurred()) {
Collin Winter670e6922007-03-21 02:57:17 +0000203 return NULL;
Victor Stinner83d52042020-12-14 22:40:40 +0100204 }
Collin Winter670e6922007-03-21 02:57:17 +0000205 Py_RETURN_NONE;
206}
207
Skip Montanaro28a181c2007-08-06 20:59:28 +0000208PyDoc_STRVAR(atexit_clear__doc__,
209"_clear() -> None\n\
210\n\
211Clear the list of previously registered exit functions.");
212
Collin Winter670e6922007-03-21 02:57:17 +0000213static PyObject *
Victor Stinner83d52042020-12-14 22:40:40 +0100214atexit_clear(PyObject *module, PyObject *unused)
Collin Winter670e6922007-03-21 02:57:17 +0000215{
Victor Stinner83d52042020-12-14 22:40:40 +0100216 atexit_cleanup(get_atexit_state(module));
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200217 Py_RETURN_NONE;
218}
219
220PyDoc_STRVAR(atexit_ncallbacks__doc__,
221"_ncallbacks() -> int\n\
222\n\
223Return the number of registered exit functions.");
224
225static PyObject *
Victor Stinner83d52042020-12-14 22:40:40 +0100226atexit_ncallbacks(PyObject *module, PyObject *unused)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200227{
Victor Stinner83d52042020-12-14 22:40:40 +0100228 struct atexit_state *state = get_atexit_state(module);
229 return PyLong_FromSsize_t(state->ncallbacks);
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200230}
231
232static int
Victor Stinner83d52042020-12-14 22:40:40 +0100233atexit_m_traverse(PyObject *module, visitproc visit, void *arg)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200234{
Victor Stinner83d52042020-12-14 22:40:40 +0100235 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];
Victor Stinner5b1ef202020-03-17 18:09:46 +0100238 if (cb == NULL)
239 continue;
240 Py_VISIT(cb->func);
241 Py_VISIT(cb->args);
242 Py_VISIT(cb->kwargs);
Collin Winter670e6922007-03-21 02:57:17 +0000243 }
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200244 return 0;
245}
246
247static int
Victor Stinner83d52042020-12-14 22:40:40 +0100248atexit_m_clear(PyObject *module)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200249{
Victor Stinner83d52042020-12-14 22:40:40 +0100250 struct atexit_state *state = (struct atexit_state *)PyModule_GetState(module);
251 atexit_cleanup(state);
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200252 return 0;
Collin Winter670e6922007-03-21 02:57:17 +0000253}
254
Stefan Krah650365b2012-03-27 11:49:21 +0200255static void
Victor Stinner83d52042020-12-14 22:40:40 +0100256atexit_free(PyObject *module)
Stefan Krah650365b2012-03-27 11:49:21 +0200257{
Victor Stinner83d52042020-12-14 22:40:40 +0100258 struct atexit_state *state = (struct atexit_state *)PyModule_GetState(module);
259 atexit_cleanup(state);
260 PyMem_Free(state->atexit_callbacks);
Stefan Krah650365b2012-03-27 11:49:21 +0200261}
262
Skip Montanaro28a181c2007-08-06 20:59:28 +0000263PyDoc_STRVAR(atexit_unregister__doc__,
264"unregister(func) -> None\n\
265\n\
Martin Panter7462b6492015-11-02 03:37:02 +0000266Unregister an exit function which was previously registered using\n\
Skip Montanaro28a181c2007-08-06 20:59:28 +0000267atexit.register\n\
268\n\
269 func - function to be unregistered");
270
Collin Winter670e6922007-03-21 02:57:17 +0000271static PyObject *
Victor Stinner83d52042020-12-14 22:40:40 +0100272atexit_unregister(PyObject *module, PyObject *func)
Collin Winter670e6922007-03-21 02:57:17 +0000273{
Victor Stinner83d52042020-12-14 22:40:40 +0100274 struct atexit_state *state = get_atexit_state(module);
275 for (int i = 0; i < state->ncallbacks; i++)
Collin Winter670e6922007-03-21 02:57:17 +0000276 {
Victor Stinner83d52042020-12-14 22:40:40 +0100277 atexit_callback *cb = state->atexit_callbacks[i];
278 if (cb == NULL) {
Collin Winter670e6922007-03-21 02:57:17 +0000279 continue;
Victor Stinner83d52042020-12-14 22:40:40 +0100280 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000281
Victor Stinner83d52042020-12-14 22:40:40 +0100282 int eq = PyObject_RichCompareBool(cb->func, func, Py_EQ);
283 if (eq < 0) {
Collin Winter670e6922007-03-21 02:57:17 +0000284 return NULL;
Victor Stinner83d52042020-12-14 22:40:40 +0100285 }
286 if (eq) {
287 atexit_delete_cb(state, i);
288 }
Collin Winter670e6922007-03-21 02:57:17 +0000289 }
290 Py_RETURN_NONE;
291}
292
Victor Stinner83d52042020-12-14 22:40:40 +0100293
Collin Winter670e6922007-03-21 02:57:17 +0000294static PyMethodDef atexit_methods[] = {
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200295 {"register", (PyCFunction)(void(*)(void)) atexit_register, METH_VARARGS|METH_KEYWORDS,
Collin Winter670e6922007-03-21 02:57:17 +0000296 atexit_register__doc__},
297 {"_clear", (PyCFunction) atexit_clear, METH_NOARGS,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000298 atexit_clear__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000299 {"unregister", (PyCFunction) atexit_unregister, METH_O,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000300 atexit_unregister__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000301 {"_run_exitfuncs", (PyCFunction) atexit_run_exitfuncs, METH_NOARGS,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000302 atexit_run_exitfuncs__doc__},
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200303 {"_ncallbacks", (PyCFunction) atexit_ncallbacks, METH_NOARGS,
304 atexit_ncallbacks__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000305 {NULL, NULL} /* sentinel */
306};
307
308/* ===================================================================== */
309/* Initialization function. */
310
311PyDoc_STRVAR(atexit__doc__,
linchiwei12352bf4702020-07-27 07:33:00 +0800312"allow programmer to define multiple exit functions to be executed\n\
Collin Winter670e6922007-03-21 02:57:17 +0000313upon normal program termination.\n\
314\n\
Skip Montanaro28a181c2007-08-06 20:59:28 +0000315Two public functions, register and unregister, are defined.\n\
Collin Winter670e6922007-03-21 02:57:17 +0000316");
317
Marcel Plch776407f2017-12-20 11:17:58 +0100318static int
Victor Stinner83d52042020-12-14 22:40:40 +0100319atexit_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) {
Marcel Plch776407f2017-12-20 11:17:58 +0100326 return -1;
Victor Stinner83d52042020-12-14 22:40:40 +0100327 }
Marcel Plch776407f2017-12-20 11:17:58 +0100328
Victor Stinner357704c2020-12-14 23:07:54 +0100329 PyInterpreterState *interp = _PyInterpreterState_GET();
330 interp->atexit_module = module;
Marcel Plch776407f2017-12-20 11:17:58 +0100331 return 0;
332}
333
334static PyModuleDef_Slot atexit_slots[] = {
335 {Py_mod_exec, atexit_exec},
336 {0, NULL}
337};
Martin v. Löwis1a214512008-06-11 05:26:20 +0000338
339static struct PyModuleDef atexitmodule = {
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200340 PyModuleDef_HEAD_INIT,
Victor Stinner83d52042020-12-14 22:40:40 +0100341 .m_name = "atexit",
342 .m_doc = atexit__doc__,
343 .m_size = sizeof(struct atexit_state),
344 .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
Martin v. Löwis1a214512008-06-11 05:26:20 +0000349};
350
Collin Winter670e6922007-03-21 02:57:17 +0000351PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000352PyInit_atexit(void)
Collin Winter670e6922007-03-21 02:57:17 +0000353{
Marcel Plch776407f2017-12-20 11:17:58 +0100354 return PyModuleDef_Init(&atexitmodule);
Collin Winter670e6922007-03-21 02:57:17 +0000355}