Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/threadframe/threadframemodule.c
blob: 2f67a45818c58c4d5dc18bb4b9c7c2e16c8f67c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
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);
}