LCOV - code coverage report
Current view: top level - libreoffice/workdir/unxlngi6.pro/UnpackedTarball/python3/Modules - atexitmodule.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 0 111 0.0 %
Date: 2012-12-17 Functions: 0 9 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.10