diff options
Diffstat (limited to 'bindings/threadframe/threadframemodule.c')
-rw-r--r-- | bindings/threadframe/threadframemodule.c | 111 |
1 files changed, 111 insertions, 0 deletions
diff --git a/bindings/threadframe/threadframemodule.c b/bindings/threadframe/threadframemodule.c new file mode 100644 index 0000000..2f67a45 --- /dev/null +++ b/bindings/threadframe/threadframemodule.c @@ -0,0 +1,111 @@ +/* + * module to access the stack frame of all Python interpreter threads + * + * works on Solaris and OS X, portability to other OSes unknown + * + * Fazal Majid, 2002-10-11 + * + * with contributions from Bob Ippolito (http://bob.pycs.net/) + * + * Copyright (c) 2002-2004 Kefta Inc. + * All rights reserved + * + */ + +#include "Python.h" +#include "compile.h" +#include "frameobject.h" +#include "patchlevel.h" + +static PyObject * +threadframe_threadframe(PyObject *self, PyObject *args) { + PyInterpreterState *interp; + PyThreadState *tstate; + PyFrameObject *frame; + PyListObject *frames; + + frames = (PyListObject*) PyList_New(0); + if (! frames) return NULL; + + /* Walk down the interpreters and threads until we find the one + matching the supplied thread ID. */ + for (interp = PyInterpreterState_Head(); interp != NULL; + interp = interp->next) { + for(tstate = interp->tstate_head; tstate != NULL; + tstate = tstate->next) { + frame = tstate->frame; + if (! frame) continue; + Py_INCREF(frame); + PyList_Append((PyObject*) frames, (PyObject*) frame); + } + } + return (PyObject*) frames; +} + +/* the PyThreadState gained a thread_id member only in 2.3rc1 */ +static PyObject * +threadframe_dict(PyObject *self, PyObject *args) { +#if PY_VERSION_HEX < 0x02030000 + PyErr_SetString(PyExc_NotImplementedError, + "threadframe.dict() requires Python 2.3 or later"); + return NULL; +#else + PyInterpreterState *interp; + PyThreadState *tstate; + PyFrameObject *frame; + PyObject *frames; + + frames = (PyObject*) PyDict_New(); + if (! frames) return NULL; + + /* Walk down the interpreters and threads until we find the one + matching the supplied thread ID. */ + for (interp = PyInterpreterState_Head(); interp != NULL; + interp = interp->next) { + for(tstate = interp->tstate_head; tstate != NULL; + tstate = tstate->next) { + PyObject *thread_id; + frame = tstate->frame; + if (! frame) continue; + thread_id = PyInt_FromLong(tstate->thread_id); + PyDict_SetItem(frames, thread_id, (PyObject*)frame); + Py_DECREF(thread_id); + } + } + return frames; +#endif +} + +static char threadframe_doc[] = +"Returns a list of frame objects for all threads.\n" +"(equivalent to dict().values() on 2.3 and later)."; + +static char threadframe_dict_doc[] = +"Returns a dictionary, mapping for all threads the thread ID\n" +"(as returned by thread.get_ident() or by the keys to threading._active)\n" +"to the corresponding frame object.\n" +"Raises NotImplementedError on Python 2.2."; + +/* List of functions defined in the module */ + +static PyMethodDef threadframe_methods[] = { + {"threadframe", threadframe_threadframe, METH_VARARGS, threadframe_doc}, + {"dict", threadframe_dict, METH_VARARGS, threadframe_dict_doc}, + {NULL, NULL} /* sentinel */ +}; + + +/* Initialization function for the module (*must* be called initthreadframe) */ + +static char module_doc[] = +"Debugging module to extract stack frames for all Python interpreter heads.\n" +"Useful in conjunction with traceback.print_stack().\n"; + +DL_EXPORT(void) +initthreadframe(void) +{ + PyObject *m; + + /* Create the module and add the functions */ + m = Py_InitModule3("threadframe", threadframe_methods, module_doc); +} |