threadframemodule.c 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * module to access the stack frame of all Python interpreter threads
  3. *
  4. * works on Solaris and OS X, portability to other OSes unknown
  5. *
  6. * Fazal Majid, 2002-10-11
  7. *
  8. * with contributions from Bob Ippolito (http://bob.pycs.net/)
  9. *
  10. * Copyright (c) 2002-2004 Kefta Inc.
  11. * All rights reserved
  12. *
  13. */
  14. #include "Python.h"
  15. #include "compile.h"
  16. #include "frameobject.h"
  17. #include "patchlevel.h"
  18. static PyObject *
  19. threadframe_threadframe(PyObject *self, PyObject *args) {
  20. PyInterpreterState *interp;
  21. PyThreadState *tstate;
  22. PyFrameObject *frame;
  23. PyListObject *frames;
  24. frames = (PyListObject*) PyList_New(0);
  25. if (! frames) return NULL;
  26. /* Walk down the interpreters and threads until we find the one
  27. matching the supplied thread ID. */
  28. for (interp = PyInterpreterState_Head(); interp != NULL;
  29. interp = interp->next) {
  30. for(tstate = interp->tstate_head; tstate != NULL;
  31. tstate = tstate->next) {
  32. frame = tstate->frame;
  33. if (! frame) continue;
  34. Py_INCREF(frame);
  35. PyList_Append((PyObject*) frames, (PyObject*) frame);
  36. }
  37. }
  38. return (PyObject*) frames;
  39. }
  40. /* the PyThreadState gained a thread_id member only in 2.3rc1 */
  41. static PyObject *
  42. threadframe_dict(PyObject *self, PyObject *args) {
  43. #if PY_VERSION_HEX < 0x02030000
  44. PyErr_SetString(PyExc_NotImplementedError,
  45. "threadframe.dict() requires Python 2.3 or later");
  46. return NULL;
  47. #else
  48. PyInterpreterState *interp;
  49. PyThreadState *tstate;
  50. PyFrameObject *frame;
  51. PyObject *frames;
  52. frames = (PyObject*) PyDict_New();
  53. if (! frames) return NULL;
  54. /* Walk down the interpreters and threads until we find the one
  55. matching the supplied thread ID. */
  56. for (interp = PyInterpreterState_Head(); interp != NULL;
  57. interp = interp->next) {
  58. for(tstate = interp->tstate_head; tstate != NULL;
  59. tstate = tstate->next) {
  60. PyObject *thread_id;
  61. frame = tstate->frame;
  62. if (! frame) continue;
  63. thread_id = PyInt_FromLong(tstate->thread_id);
  64. PyDict_SetItem(frames, thread_id, (PyObject*)frame);
  65. Py_DECREF(thread_id);
  66. }
  67. }
  68. return frames;
  69. #endif
  70. }
  71. static char threadframe_doc[] =
  72. "Returns a list of frame objects for all threads.\n"
  73. "(equivalent to dict().values() on 2.3 and later).";
  74. static char threadframe_dict_doc[] =
  75. "Returns a dictionary, mapping for all threads the thread ID\n"
  76. "(as returned by thread.get_ident() or by the keys to threading._active)\n"
  77. "to the corresponding frame object.\n"
  78. "Raises NotImplementedError on Python 2.2.";
  79. /* List of functions defined in the module */
  80. static PyMethodDef threadframe_methods[] = {
  81. {"threadframe", threadframe_threadframe, METH_VARARGS, threadframe_doc},
  82. {"dict", threadframe_dict, METH_VARARGS, threadframe_dict_doc},
  83. {NULL, NULL} /* sentinel */
  84. };
  85. /* Initialization function for the module (*must* be called initthreadframe) */
  86. static char module_doc[] =
  87. "Debugging module to extract stack frames for all Python interpreter heads.\n"
  88. "Useful in conjunction with traceback.print_stack().\n";
  89. DL_EXPORT(void)
  90. initthreadframe(void)
  91. {
  92. PyObject *m;
  93. /* Create the module and add the functions */
  94. m = Py_InitModule3("threadframe", threadframe_methods, module_doc);
  95. }