You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

309 lines
7.8 KiB

  1. /*
  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. #include "Python.h"
  9. /* Forward declaration (for atexit_cleanup) */
  10. static PyObject *atexit_clear(PyObject*, PyObject*);
  11. /* Forward declaration (for atexit_callfuncs) */
  12. static void atexit_cleanup(PyObject*);
  13. /* Forward declaration of module object */
  14. static struct PyModuleDef atexitmodule;
  15. /* ===================================================================== */
  16. /* Callback machinery. */
  17. typedef struct {
  18. PyObject *func;
  19. PyObject *args;
  20. PyObject *kwargs;
  21. } atexit_callback;
  22. typedef struct {
  23. atexit_callback **atexit_callbacks;
  24. int ncallbacks;
  25. int callback_len;
  26. } atexitmodule_state;
  27. #define GET_ATEXIT_STATE(mod) ((atexitmodule_state*)PyModule_GetState(mod))
  28. /* Installed into pythonrun.c's atexit mechanism */
  29. static void
  30. atexit_callfuncs(void)
  31. {
  32. PyObject *exc_type = NULL, *exc_value, *exc_tb, *r;
  33. atexit_callback *cb;
  34. PyObject *module;
  35. atexitmodule_state *modstate;
  36. int i;
  37. module = PyState_FindModule(&atexitmodule);
  38. if (module == NULL)
  39. return;
  40. modstate = GET_ATEXIT_STATE(module);
  41. if (modstate->ncallbacks == 0)
  42. return;
  43. for (i = modstate->ncallbacks - 1; i >= 0; i--)
  44. {
  45. cb = modstate->atexit_callbacks[i];
  46. if (cb == NULL)
  47. continue;
  48. r = PyObject_Call(cb->func, cb->args, cb->kwargs);
  49. Py_XDECREF(r);
  50. if (r == NULL) {
  51. /* Maintain the last exception, but don't leak if there are
  52. multiple exceptions. */
  53. if (exc_type) {
  54. Py_DECREF(exc_type);
  55. Py_XDECREF(exc_value);
  56. Py_XDECREF(exc_tb);
  57. }
  58. PyErr_Fetch(&exc_type, &exc_value, &exc_tb);
  59. if (!PyErr_ExceptionMatches(PyExc_SystemExit)) {
  60. PySys_WriteStderr("Error in atexit._run_exitfuncs:\n");
  61. PyErr_NormalizeException(&exc_type, &exc_value, &exc_tb);
  62. PyErr_Display(exc_type, exc_value, exc_tb);
  63. }
  64. }
  65. }
  66. atexit_cleanup(module);
  67. if (exc_type)
  68. PyErr_Restore(exc_type, exc_value, exc_tb);
  69. }
  70. static void
  71. atexit_delete_cb(PyObject *self, int i)
  72. {
  73. atexitmodule_state *modstate;
  74. atexit_callback *cb;
  75. modstate = GET_ATEXIT_STATE(self);
  76. cb = modstate->atexit_callbacks[i];
  77. modstate->atexit_callbacks[i] = NULL;
  78. Py_DECREF(cb->func);
  79. Py_DECREF(cb->args);
  80. Py_XDECREF(cb->kwargs);
  81. PyMem_Free(cb);
  82. }
  83. static void
  84. atexit_cleanup(PyObject *self)
  85. {
  86. PyObject *r = atexit_clear(self, NULL);
  87. Py_DECREF(r);
  88. }
  89. /* ===================================================================== */
  90. /* Module methods. */
  91. PyDoc_STRVAR(atexit_register__doc__,
  92. "register(func, *args, **kwargs) -> func\n\
  93. \n\
  94. Register a function to be executed upon normal program termination\n\
  95. \n\
  96. func - function to be called at exit\n\
  97. args - optional arguments to pass to func\n\
  98. kwargs - optional keyword arguments to pass to func\n\
  99. \n\
  100. func is returned to facilitate usage as a decorator.");
  101. static PyObject *
  102. atexit_register(PyObject *self, PyObject *args, PyObject *kwargs)
  103. {
  104. atexitmodule_state *modstate;
  105. atexit_callback *new_callback;
  106. PyObject *func = NULL;
  107. modstate = GET_ATEXIT_STATE(self);
  108. if (modstate->ncallbacks >= modstate->callback_len) {
  109. atexit_callback **r;
  110. modstate->callback_len += 16;
  111. r = (atexit_callback**)PyMem_Realloc(modstate->atexit_callbacks,
  112. sizeof(atexit_callback*) * modstate->callback_len);
  113. if (r == NULL)
  114. return PyErr_NoMemory();
  115. modstate->atexit_callbacks = r;
  116. }
  117. if (PyTuple_GET_SIZE(args) == 0) {
  118. PyErr_SetString(PyExc_TypeError,
  119. "register() takes at least 1 argument (0 given)");
  120. return NULL;
  121. }
  122. func = PyTuple_GET_ITEM(args, 0);
  123. if (!PyCallable_Check(func)) {
  124. PyErr_SetString(PyExc_TypeError,
  125. "the first argument must be callable");
  126. return NULL;
  127. }
  128. new_callback = PyMem_Malloc(sizeof(atexit_callback));
  129. if (new_callback == NULL)
  130. return PyErr_NoMemory();
  131. new_callback->args = PyTuple_GetSlice(args, 1, PyTuple_GET_SIZE(args));
  132. if (new_callback->args == NULL) {
  133. PyMem_Free(new_callback);
  134. return NULL;
  135. }
  136. new_callback->func = func;
  137. new_callback->kwargs = kwargs;
  138. Py_INCREF(func);
  139. Py_XINCREF(kwargs);
  140. modstate->atexit_callbacks[modstate->ncallbacks++] = new_callback;
  141. Py_INCREF(func);
  142. return func;
  143. }
  144. PyDoc_STRVAR(atexit_run_exitfuncs__doc__,
  145. "_run_exitfuncs() -> None\n\
  146. \n\
  147. Run all registered exit functions.");
  148. static PyObject *
  149. atexit_run_exitfuncs(PyObject *self, PyObject *unused)
  150. {
  151. atexit_callfuncs();
  152. if (PyErr_Occurred())
  153. return NULL;
  154. Py_RETURN_NONE;
  155. }
  156. PyDoc_STRVAR(atexit_clear__doc__,
  157. "_clear() -> None\n\
  158. \n\
  159. Clear the list of previously registered exit functions.");
  160. static PyObject *
  161. atexit_clear(PyObject *self, PyObject *unused)
  162. {
  163. atexitmodule_state *modstate;
  164. atexit_callback *cb;
  165. int i;
  166. modstate = GET_ATEXIT_STATE(self);
  167. for (i = 0; i < modstate->ncallbacks; i++) {
  168. cb = modstate->atexit_callbacks[i];
  169. if (cb == NULL)
  170. continue;
  171. atexit_delete_cb(self, i);
  172. }
  173. modstate->ncallbacks = 0;
  174. Py_RETURN_NONE;
  175. }
  176. static void
  177. atexit_free(PyObject *m)
  178. {
  179. atexitmodule_state *modstate;
  180. modstate = GET_ATEXIT_STATE(m);
  181. PyMem_Free(modstate->atexit_callbacks);
  182. }
  183. PyDoc_STRVAR(atexit_unregister__doc__,
  184. "unregister(func) -> None\n\
  185. \n\
  186. Unregister a exit function which was previously registered using\n\
  187. atexit.register\n\
  188. \n\
  189. func - function to be unregistered");
  190. static PyObject *
  191. atexit_unregister(PyObject *self, PyObject *func)
  192. {
  193. atexitmodule_state *modstate;
  194. atexit_callback *cb;
  195. int i, eq;
  196. modstate = GET_ATEXIT_STATE(self);
  197. for (i = 0; i < modstate->ncallbacks; i++)
  198. {
  199. cb = modstate->atexit_callbacks[i];
  200. if (cb == NULL)
  201. continue;
  202. eq = PyObject_RichCompareBool(cb->func, func, Py_EQ);
  203. if (eq < 0)
  204. return NULL;
  205. if (eq)
  206. atexit_delete_cb(self, i);
  207. }
  208. Py_RETURN_NONE;
  209. }
  210. static PyMethodDef atexit_methods[] = {
  211. {"register", (PyCFunction) atexit_register, METH_VARARGS|METH_KEYWORDS,
  212. atexit_register__doc__},
  213. {"_clear", (PyCFunction) atexit_clear, METH_NOARGS,
  214. atexit_clear__doc__},
  215. {"unregister", (PyCFunction) atexit_unregister, METH_O,
  216. atexit_unregister__doc__},
  217. {"_run_exitfuncs", (PyCFunction) atexit_run_exitfuncs, METH_NOARGS,
  218. atexit_run_exitfuncs__doc__},
  219. {NULL, NULL} /* sentinel */
  220. };
  221. /* ===================================================================== */
  222. /* Initialization function. */
  223. PyDoc_STRVAR(atexit__doc__,
  224. "allow programmer to define multiple exit functions to be executed\
  225. upon normal program termination.\n\
  226. \n\
  227. Two public functions, register and unregister, are defined.\n\
  228. ");
  229. static struct PyModuleDef atexitmodule = {
  230. PyModuleDef_HEAD_INIT,
  231. "atexit",
  232. atexit__doc__,
  233. sizeof(atexitmodule_state),
  234. atexit_methods,
  235. NULL,
  236. NULL,
  237. NULL,
  238. (freefunc)atexit_free
  239. };
  240. PyMODINIT_FUNC
  241. PyInit_atexit(void)
  242. {
  243. PyObject *m;
  244. atexitmodule_state *modstate;
  245. m = PyModule_Create(&atexitmodule);
  246. if (m == NULL)
  247. return NULL;
  248. modstate = GET_ATEXIT_STATE(m);
  249. modstate->callback_len = 32;
  250. modstate->ncallbacks = 0;
  251. modstate->atexit_callbacks = PyMem_New(atexit_callback*,
  252. modstate->callback_len);
  253. if (modstate->atexit_callbacks == NULL)
  254. return NULL;
  255. _Py_PyAtExit(atexit_callfuncs);
  256. return m;
  257. }