diff --git a/devsupApp/src/setup.c b/devsupApp/src/setup.c index ee92511..1a6f94f 100644 --- a/devsupApp/src/setup.c +++ b/devsupApp/src/setup.c @@ -23,9 +23,6 @@ #include "pydevsup.h" -/* dictionary of initHook names */ -static PyObject *hooktable; - typedef struct { const initHookState state; const char * const name; @@ -98,46 +95,30 @@ void evalFilePy(const char* file) static void pyhook(initHookState state) { + static int madenoise = 0; PyGILState_STATE gilstate; + PyObject *mod, *ret; + + /* ignore deprecated init hooks */ + if(state==initHookAfterInterruptAccept || state==initHookAtEnd) + return; gilstate = PyGILState_Ensure(); - if(hooktable && PyDict_Check(hooktable)) { - PyObject *next; - PyObject *key = PyInt_FromLong((long)state); - PyObject *list = PyDict_GetItem(hooktable, key); - Py_DECREF(key); - - if(list) { - - list = PyObject_GetIter(list); - if(!list) { - fprintf(stderr, "hook sequence not iterable!"); - - } else { - - while((next=PyIter_Next(list))!=NULL) { - PyObject *obj; - if(!PyCallable_Check(next)) - continue; - obj = PyObject_CallFunction(next, ""); - Py_DECREF(next); - if(obj) - Py_DECREF(obj); - else { - PyErr_Print(); - PyErr_Clear(); - } - } - if(!PyErr_Occurred()) { - PyErr_Print(); - PyErr_Clear(); - } - - Py_DECREF(list); - } - } + mod = PyImport_ImportModule("devsup.hooks"); + if(!mod) { + if(!madenoise) + fprintf(stderr, "Couldn't import devsup.hooks\n"); + madenoise=1; + return; } + ret = PyObject_CallMethod(mod, "_runhook", "l", (long)state); + Py_DECREF(mod); + if(PyErr_Occurred()) { + PyErr_Print(); + PyErr_Clear(); + } + Py_XDECREF(ret); PyGILState_Release(gilstate); } @@ -174,10 +155,6 @@ PyMODINIT_FUNC init_dbapi(void) import_array(); - hooktable = PyDict_New(); - if(!hooktable) - MODINIT_RET(NULL); - if(pyField_prepare()) MODINIT_RET(NULL); if(pyRecord_prepare()) @@ -202,8 +179,6 @@ PyMODINIT_FUNC init_dbapi(void) for(st = statenames; st->name; st++) { PyDict_SetItemString(hookdict, st->name, PyInt_FromLong((long)st->state)); } - Py_INCREF(hooktable); /* an extra ref for the global pointer */ - PyModule_AddObject(mod, "_hooktable", hooktable); pyField_setup(mod); pyRecord_setup(mod); @@ -224,10 +199,6 @@ static void cleanupPy(void *junk) pyField_cleanup(); - /* release extra reference for hooktable */ - Py_XDECREF(hooktable); - hooktable = NULL; - Py_Finalize(); } diff --git a/python/devsup/hooks.py b/python/devsup/hooks.py index e2c800c..559c4e4 100644 --- a/python/devsup/hooks.py +++ b/python/devsup/hooks.py @@ -1,5 +1,8 @@ from __future__ import print_function +import traceback +from collections import defaultdict + try: import _dbapi except ImportError: @@ -13,12 +16,16 @@ __all__ = [ hooknames = _dbapi._hooks.keys() +_revnames = dict([(v,k) for k,v in _dbapi._hooks.iteritems()]) + +_hooktable = defaultdict(list) + def addHook(state, func): """addHook("stats", funcion) Add callable to IOC start sequence. - Callables are run in the reverse of the order in - which they were added. + Callables are run in the order in + which they were added (except for 'AtIocExit'). >>> def show(): ... print 'State Occurred' @@ -28,13 +35,7 @@ def addHook(state, func): for cleanup actions during IOC shutdown. """ sid = _dbapi._hooks[state] - try: - slist = _dbapi._hooktable[sid] - except KeyError: - slist = [] - _dbapi._hooktable[sid] = slist - - slist.append(func) + _hooktable[sid].append(func) def debugHooks(): @@ -44,3 +45,16 @@ def debugHooks(): def _showstate(state=h): print('Reached state',state) addHook(h, _showstate) + +def _runhook(sid): + name = _revnames[sid] + pop = -1 if name=='AtIocExit' else 0 + fns = _hooktable.get(sid) + if fns is not None: + while len(fns)>0: + fn = fns.pop(pop) + try: + fn() + except: + print("Error running",name,"hook",fn) + traceback.print_exc()