blob: ae13eae75dbaecdeb76348240f38ded4ad0daa29 [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 Stinnerb8fa1352020-12-15 14:34:19 +010010#include "pycore_initconfig.h" // _PyStatus_NO_MEMORY
11#include "pycore_interp.h" // PyInterpreterState.atexit
Victor Stinner83d52042020-12-14 22:40:40 +010012#include "pycore_pystate.h" // _PyInterpreterState_GET
Collin Winter3e81ec82007-03-23 22:46:49 +000013
Collin Winter670e6922007-03-21 02:57:17 +000014/* ===================================================================== */
15/* Callback machinery. */
16
Victor Stinner83d52042020-12-14 22:40:40 +010017static inline struct atexit_state*
Victor Stinnerb8fa1352020-12-15 14:34:19 +010018get_atexit_state(void)
Hai Shif707d942020-03-16 21:15:01 +080019{
Victor Stinnerb8fa1352020-12-15 14:34:19 +010020 PyInterpreterState *interp = _PyInterpreterState_GET();
21 return &interp->atexit;
Hai Shif707d942020-03-16 21:15:01 +080022}
Christian Heimes9c94ba42008-10-30 21:34:02 +000023
Collin Winter670e6922007-03-21 02:57:17 +000024
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020025static void
Victor Stinner83d52042020-12-14 22:40:40 +010026atexit_delete_cb(struct atexit_state *state, int i)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020027{
Victor Stinnerb8fa1352020-12-15 14:34:19 +010028 atexit_callback *cb = state->callbacks[i];
29 state->callbacks[i] = NULL;
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020030
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020031 Py_DECREF(cb->func);
32 Py_DECREF(cb->args);
33 Py_XDECREF(cb->kwargs);
34 PyMem_Free(cb);
35}
36
Victor Stinner83d52042020-12-14 22:40:40 +010037
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020038/* Clear all callbacks without calling them */
39static void
Victor Stinner83d52042020-12-14 22:40:40 +010040atexit_cleanup(struct atexit_state *state)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020041{
42 atexit_callback *cb;
Victor Stinner83d52042020-12-14 22:40:40 +010043 for (int i = 0; i < state->ncallbacks; i++) {
Victor Stinnerb8fa1352020-12-15 14:34:19 +010044 cb = state->callbacks[i];
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020045 if (cb == NULL)
46 continue;
47
Victor Stinner83d52042020-12-14 22:40:40 +010048 atexit_delete_cb(state, i);
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020049 }
Victor Stinner83d52042020-12-14 22:40:40 +010050 state->ncallbacks = 0;
Antoine Pitrou2d350fd2013-08-01 20:56:12 +020051}
52
Victor Stinnerb8fa1352020-12-15 14:34:19 +010053
54PyStatus
55_PyAtExit_Init(PyThreadState *tstate)
56{
57 struct atexit_state *state = &tstate->interp->atexit;
58 // _PyAtExit_Init() must only be called once
59 assert(state->callbacks == NULL);
60
61 state->callback_len = 32;
62 state->ncallbacks = 0;
63 state->callbacks = PyMem_New(atexit_callback*, state->callback_len);
64 if (state->callbacks == NULL) {
65 return _PyStatus_NO_MEMORY();
66 }
67 return _PyStatus_OK();
68}
69
70
71void
72_PyAtExit_Fini(PyInterpreterState *interp)
73{
74 struct atexit_state *state = &interp->atexit;
75 atexit_cleanup(state);
76 PyMem_Free(state->callbacks);
77}
78
Collin Winter670e6922007-03-21 02:57:17 +000079
Skip Montanaro711552b2008-09-23 00:52:29 +000080static void
Victor Stinnerb8fa1352020-12-15 14:34:19 +010081atexit_callfuncs(struct atexit_state *state, int ignore_exc)
Collin Winter670e6922007-03-21 02:57:17 +000082{
Victor Stinner83d52042020-12-14 22:40:40 +010083 assert(!PyErr_Occurred());
Christian Heimes9c94ba42008-10-30 21:34:02 +000084
Victor Stinner83d52042020-12-14 22:40:40 +010085 if (state->ncallbacks == 0) {
Christian Heimes9c94ba42008-10-30 21:34:02 +000086 return;
Victor Stinner83d52042020-12-14 22:40:40 +010087 }
Christian Heimes9c94ba42008-10-30 21:34:02 +000088
Victor Stinner83d52042020-12-14 22:40:40 +010089 PyObject *exc_type = NULL, *exc_value, *exc_tb;
90 for (int i = state->ncallbacks - 1; i >= 0; i--) {
Victor Stinnerb8fa1352020-12-15 14:34:19 +010091 atexit_callback *cb = state->callbacks[i];
Victor Stinner83d52042020-12-14 22:40:40 +010092 if (cb == NULL) {
Collin Winter670e6922007-03-21 02:57:17 +000093 continue;
Victor Stinner83d52042020-12-14 22:40:40 +010094 }
Collin Winter670e6922007-03-21 02:57:17 +000095
Victor Stinner83d52042020-12-14 22:40:40 +010096 PyObject *res = PyObject_Call(cb->func, cb->args, cb->kwargs);
97 if (res == NULL) {
Victor Stinner357704c2020-12-14 23:07:54 +010098 if (ignore_exc) {
99 _PyErr_WriteUnraisableMsg("in atexit callback", cb->func);
Collin Winter670e6922007-03-21 02:57:17 +0000100 }
Victor Stinner357704c2020-12-14 23:07:54 +0100101 else {
102 /* Maintain the last exception, but don't leak if there are
103 multiple exceptions. */
104 if (exc_type) {
105 Py_DECREF(exc_type);
106 Py_XDECREF(exc_value);
107 Py_XDECREF(exc_tb);
108 }
109 PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
110 if (!PyErr_GivenExceptionMatches(exc_type, PyExc_SystemExit)) {
111 PySys_WriteStderr("Error in atexit._run_exitfuncs:\n");
112 PyErr_NormalizeException(&exc_type, &exc_value, &exc_tb);
113 PyErr_Display(exc_type, exc_value, exc_tb);
114 }
Collin Winter670e6922007-03-21 02:57:17 +0000115 }
116 }
Victor Stinner83d52042020-12-14 22:40:40 +0100117 else {
118 Py_DECREF(res);
119 }
Collin Winter670e6922007-03-21 02:57:17 +0000120 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000121
Victor Stinner83d52042020-12-14 22:40:40 +0100122 atexit_cleanup(state);
Skip Montanaro711552b2008-09-23 00:52:29 +0000123
Victor Stinner357704c2020-12-14 23:07:54 +0100124 if (ignore_exc) {
125 assert(!PyErr_Occurred());
126 }
127 else {
128 if (exc_type) {
129 PyErr_Restore(exc_type, exc_value, exc_tb);
130 }
Victor Stinner83d52042020-12-14 22:40:40 +0100131 }
Collin Winter670e6922007-03-21 02:57:17 +0000132}
133
Victor Stinner357704c2020-12-14 23:07:54 +0100134
135void
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100136_PyAtExit_Call(PyThreadState *tstate)
Victor Stinner357704c2020-12-14 23:07:54 +0100137{
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100138 struct atexit_state *state = &tstate->interp->atexit;
139 atexit_callfuncs(state, 1);
Victor Stinner357704c2020-12-14 23:07:54 +0100140}
141
142
Collin Winter670e6922007-03-21 02:57:17 +0000143/* ===================================================================== */
144/* Module methods. */
145
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100146
Collin Winter670e6922007-03-21 02:57:17 +0000147PyDoc_STRVAR(atexit_register__doc__,
148"register(func, *args, **kwargs) -> func\n\
149\n\
150Register a function to be executed upon normal program termination\n\
151\n\
152 func - function to be called at exit\n\
153 args - optional arguments to pass to func\n\
154 kwargs - optional keyword arguments to pass to func\n\
155\n\
156 func is returned to facilitate usage as a decorator.");
157
158static PyObject *
Victor Stinner83d52042020-12-14 22:40:40 +0100159atexit_register(PyObject *module, PyObject *args, PyObject *kwargs)
Collin Winter670e6922007-03-21 02:57:17 +0000160{
Collin Winter670e6922007-03-21 02:57:17 +0000161 if (PyTuple_GET_SIZE(args) == 0) {
162 PyErr_SetString(PyExc_TypeError,
163 "register() takes at least 1 argument (0 given)");
Serhiy Storchaka009b8112015-03-18 21:53:15 +0200164 return NULL;
Collin Winter670e6922007-03-21 02:57:17 +0000165 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000166
Victor Stinner83d52042020-12-14 22:40:40 +0100167 PyObject *func = PyTuple_GET_ITEM(args, 0);
Collin Winter670e6922007-03-21 02:57:17 +0000168 if (!PyCallable_Check(func)) {
169 PyErr_SetString(PyExc_TypeError,
170 "the first argument must be callable");
171 return NULL;
172 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000173
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100174 struct atexit_state *state = get_atexit_state();
Victor Stinner83d52042020-12-14 22:40:40 +0100175 if (state->ncallbacks >= state->callback_len) {
176 atexit_callback **r;
177 state->callback_len += 16;
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100178 size_t size = sizeof(atexit_callback*) * (size_t)state->callback_len;
179 r = (atexit_callback**)PyMem_Realloc(state->callbacks, size);
Victor Stinner83d52042020-12-14 22:40:40 +0100180 if (r == NULL)
181 return PyErr_NoMemory();
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100182 state->callbacks = r;
Victor Stinner83d52042020-12-14 22:40:40 +0100183 }
Collin Winter670e6922007-03-21 02:57:17 +0000184
Victor Stinner83d52042020-12-14 22:40:40 +0100185 atexit_callback *callback = PyMem_Malloc(sizeof(atexit_callback));
186 if (callback == NULL) {
187 return PyErr_NoMemory();
188 }
189
190 callback->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
191 if (callback->args == NULL) {
192 PyMem_Free(callback);
Collin Winter670e6922007-03-21 02:57:17 +0000193 return NULL;
194 }
Victor Stinner83d52042020-12-14 22:40:40 +0100195 callback->func = Py_NewRef(func);
196 callback->kwargs = Py_XNewRef(kwargs);
Christian Heimes9c94ba42008-10-30 21:34:02 +0000197
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100198 state->callbacks[state->ncallbacks++] = callback;
Christian Heimes9c94ba42008-10-30 21:34:02 +0000199
Victor Stinner83d52042020-12-14 22:40:40 +0100200 return Py_NewRef(func);
Collin Winter670e6922007-03-21 02:57:17 +0000201}
202
Skip Montanaro28a181c2007-08-06 20:59:28 +0000203PyDoc_STRVAR(atexit_run_exitfuncs__doc__,
204"_run_exitfuncs() -> None\n\
205\n\
206Run all registered exit functions.");
207
Collin Winter670e6922007-03-21 02:57:17 +0000208static PyObject *
Victor Stinner83d52042020-12-14 22:40:40 +0100209atexit_run_exitfuncs(PyObject *module, PyObject *unused)
Collin Winter670e6922007-03-21 02:57:17 +0000210{
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100211 struct atexit_state *state = get_atexit_state();
212 atexit_callfuncs(state, 0);
Victor Stinner83d52042020-12-14 22:40:40 +0100213 if (PyErr_Occurred()) {
Collin Winter670e6922007-03-21 02:57:17 +0000214 return NULL;
Victor Stinner83d52042020-12-14 22:40:40 +0100215 }
Collin Winter670e6922007-03-21 02:57:17 +0000216 Py_RETURN_NONE;
217}
218
Skip Montanaro28a181c2007-08-06 20:59:28 +0000219PyDoc_STRVAR(atexit_clear__doc__,
220"_clear() -> None\n\
221\n\
222Clear the list of previously registered exit functions.");
223
Collin Winter670e6922007-03-21 02:57:17 +0000224static PyObject *
Victor Stinner83d52042020-12-14 22:40:40 +0100225atexit_clear(PyObject *module, PyObject *unused)
Collin Winter670e6922007-03-21 02:57:17 +0000226{
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100227 atexit_cleanup(get_atexit_state());
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200228 Py_RETURN_NONE;
229}
230
231PyDoc_STRVAR(atexit_ncallbacks__doc__,
232"_ncallbacks() -> int\n\
233\n\
234Return the number of registered exit functions.");
235
236static PyObject *
Victor Stinner83d52042020-12-14 22:40:40 +0100237atexit_ncallbacks(PyObject *module, PyObject *unused)
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200238{
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100239 struct atexit_state *state = get_atexit_state();
Victor Stinner83d52042020-12-14 22:40:40 +0100240 return PyLong_FromSsize_t(state->ncallbacks);
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200241}
242
Skip Montanaro28a181c2007-08-06 20:59:28 +0000243PyDoc_STRVAR(atexit_unregister__doc__,
244"unregister(func) -> None\n\
245\n\
Martin Panter7462b6492015-11-02 03:37:02 +0000246Unregister an exit function which was previously registered using\n\
Skip Montanaro28a181c2007-08-06 20:59:28 +0000247atexit.register\n\
248\n\
249 func - function to be unregistered");
250
Collin Winter670e6922007-03-21 02:57:17 +0000251static PyObject *
Victor Stinner83d52042020-12-14 22:40:40 +0100252atexit_unregister(PyObject *module, PyObject *func)
Collin Winter670e6922007-03-21 02:57:17 +0000253{
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100254 struct atexit_state *state = get_atexit_state();
Victor Stinner83d52042020-12-14 22:40:40 +0100255 for (int i = 0; i < state->ncallbacks; i++)
Collin Winter670e6922007-03-21 02:57:17 +0000256 {
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100257 atexit_callback *cb = state->callbacks[i];
Victor Stinner83d52042020-12-14 22:40:40 +0100258 if (cb == NULL) {
Collin Winter670e6922007-03-21 02:57:17 +0000259 continue;
Victor Stinner83d52042020-12-14 22:40:40 +0100260 }
Christian Heimes9c94ba42008-10-30 21:34:02 +0000261
Victor Stinner83d52042020-12-14 22:40:40 +0100262 int eq = PyObject_RichCompareBool(cb->func, func, Py_EQ);
263 if (eq < 0) {
Collin Winter670e6922007-03-21 02:57:17 +0000264 return NULL;
Victor Stinner83d52042020-12-14 22:40:40 +0100265 }
266 if (eq) {
267 atexit_delete_cb(state, i);
268 }
Collin Winter670e6922007-03-21 02:57:17 +0000269 }
270 Py_RETURN_NONE;
271}
272
Victor Stinner83d52042020-12-14 22:40:40 +0100273
Collin Winter670e6922007-03-21 02:57:17 +0000274static PyMethodDef atexit_methods[] = {
Serhiy Storchaka62be7422018-11-27 13:27:31 +0200275 {"register", (PyCFunction)(void(*)(void)) atexit_register, METH_VARARGS|METH_KEYWORDS,
Collin Winter670e6922007-03-21 02:57:17 +0000276 atexit_register__doc__},
277 {"_clear", (PyCFunction) atexit_clear, METH_NOARGS,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000278 atexit_clear__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000279 {"unregister", (PyCFunction) atexit_unregister, METH_O,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000280 atexit_unregister__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000281 {"_run_exitfuncs", (PyCFunction) atexit_run_exitfuncs, METH_NOARGS,
Skip Montanaro28a181c2007-08-06 20:59:28 +0000282 atexit_run_exitfuncs__doc__},
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200283 {"_ncallbacks", (PyCFunction) atexit_ncallbacks, METH_NOARGS,
284 atexit_ncallbacks__doc__},
Collin Winter670e6922007-03-21 02:57:17 +0000285 {NULL, NULL} /* sentinel */
286};
287
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100288
Collin Winter670e6922007-03-21 02:57:17 +0000289/* ===================================================================== */
290/* Initialization function. */
291
292PyDoc_STRVAR(atexit__doc__,
linchiwei12352bf4702020-07-27 07:33:00 +0800293"allow programmer to define multiple exit functions to be executed\n\
Collin Winter670e6922007-03-21 02:57:17 +0000294upon normal program termination.\n\
295\n\
Skip Montanaro28a181c2007-08-06 20:59:28 +0000296Two public functions, register and unregister, are defined.\n\
Collin Winter670e6922007-03-21 02:57:17 +0000297");
298
Martin v. Löwis1a214512008-06-11 05:26:20 +0000299static struct PyModuleDef atexitmodule = {
Antoine Pitrou2d350fd2013-08-01 20:56:12 +0200300 PyModuleDef_HEAD_INIT,
Victor Stinner83d52042020-12-14 22:40:40 +0100301 .m_name = "atexit",
302 .m_doc = atexit__doc__,
Victor Stinnerb8fa1352020-12-15 14:34:19 +0100303 .m_size = 0,
Victor Stinner83d52042020-12-14 22:40:40 +0100304 .m_methods = atexit_methods,
Martin v. Löwis1a214512008-06-11 05:26:20 +0000305};
306
Collin Winter670e6922007-03-21 02:57:17 +0000307PyMODINIT_FUNC
Martin v. Löwis1a214512008-06-11 05:26:20 +0000308PyInit_atexit(void)
Collin Winter670e6922007-03-21 02:57:17 +0000309{
Marcel Plch776407f2017-12-20 11:17:58 +0100310 return PyModuleDef_Init(&atexitmodule);
Collin Winter670e6922007-03-21 02:57:17 +0000311}