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.

301 lines
7.6 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. PyDoc_STRVAR(atexit_unregister__doc__,
  177. "unregister(func) -> None\n\
  178. \n\
  179. Unregister a exit function which was previously registered using\n\
  180. atexit.register\n\
  181. \n\
  182. func - function to be unregistered");
  183. static PyObject *
  184. atexit_unregister(PyObject *self, PyObject *func)
  185. {
  186. atexitmodule_state *modstate;
  187. atexit_callback *cb;
  188. int i, eq;
  189. modstate = GET_ATEXIT_STATE(self);
  190. for (i = 0; i < modstate->ncallbacks; i++)
  191. {
  192. cb = modstate->atexit_callbacks[i];
  193. if (cb == NULL)
  194. continue;
  195. eq = PyObject_RichCompareBool(cb->func, func, Py_EQ);
  196. if (eq < 0)
  197. return NULL;
  198. if (eq)
  199. atexit_delete_cb(self, i);
  200. }
  201. Py_RETURN_NONE;
  202. }
  203. static PyMethodDef atexit_methods[] = {
  204. {"register", (PyCFunction) atexit_register, METH_VARARGS|METH_KEYWORDS,
  205. atexit_register__doc__},
  206. {"_clear", (PyCFunction) atexit_clear, METH_NOARGS,
  207. atexit_clear__doc__},
  208. {"unregister", (PyCFunction) atexit_unregister, METH_O,
  209. atexit_unregister__doc__},
  210. {"_run_exitfuncs", (PyCFunction) atexit_run_exitfuncs, METH_NOARGS,
  211. atexit_run_exitfuncs__doc__},
  212. {NULL, NULL} /* sentinel */
  213. };
  214. /* ===================================================================== */
  215. /* Initialization function. */
  216. PyDoc_STRVAR(atexit__doc__,
  217. "allow programmer to define multiple exit functions to be executed\
  218. upon normal program termination.\n\
  219. \n\
  220. Two public functions, register and unregister, are defined.\n\
  221. ");
  222. static struct PyModuleDef atexitmodule = {
  223. PyModuleDef_HEAD_INIT,
  224. "atexit",
  225. atexit__doc__,
  226. sizeof(atexitmodule_state),
  227. atexit_methods,
  228. NULL,
  229. NULL,
  230. NULL,
  231. NULL
  232. };
  233. PyMODINIT_FUNC
  234. PyInit_atexit(void)
  235. {
  236. PyObject *m;
  237. atexitmodule_state *modstate;
  238. m = PyModule_Create(&atexitmodule);
  239. if (m == NULL)
  240. return NULL;
  241. modstate = GET_ATEXIT_STATE(m);
  242. modstate->callback_len = 32;
  243. modstate->ncallbacks = 0;
  244. modstate->atexit_callbacks = PyMem_New(atexit_callback*,
  245. modstate->callback_len);
  246. if (modstate->atexit_callbacks == NULL)
  247. return NULL;
  248. _Py_PyAtExit(atexit_callfuncs);
  249. return m;
  250. }