GDB (xrefs)
py-infthread.c
Go to the documentation of this file.
1 /* Python interface to inferior threads.
2 
3  Copyright (C) 2009-2015 Free Software Foundation, Inc.
4 
5  This file is part of GDB.
6 
7  This program is free software; you can redistribute it and/or modify
8  it under the terms of the GNU General Public License as published by
9  the Free Software Foundation; either version 3 of the License, or
10  (at your option) any later version.
11 
12  This program is distributed in the hope that it will be useful,
13  but WITHOUT ANY WARRANTY; without even the implied warranty of
14  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  GNU General Public License for more details.
16 
17  You should have received a copy of the GNU General Public License
18  along with this program. If not, see <http://www.gnu.org/licenses/>. */
19 
20 #include "defs.h"
21 #include "gdbthread.h"
22 #include "inferior.h"
23 #include "python-internal.h"
24 
25 extern PyTypeObject thread_object_type
26  CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("thread_object");
27 
28 /* Require that INFERIOR be a valid inferior ID. */
29 #define THPY_REQUIRE_VALID(Thread) \
30  do { \
31  if (!Thread->thread) \
32  { \
33  PyErr_SetString (PyExc_RuntimeError, \
34  _("Thread no longer exists.")); \
35  return NULL; \
36  } \
37  } while (0)
38 
41 {
42  thread_object *thread_obj;
43 
44  thread_obj = PyObject_New (thread_object, &thread_object_type);
45  if (!thread_obj)
46  return NULL;
47 
48  thread_obj->thread = tp;
49  thread_obj->inf_obj = find_inferior_object (ptid_get_pid (tp->ptid));
50 
51  return thread_obj;
52 }
53 
54 static void
55 thpy_dealloc (PyObject *self)
56 {
57  Py_DECREF (((thread_object *) self)->inf_obj);
58  Py_TYPE (self)->tp_free (self);
59 }
60 
61 static PyObject *
62 thpy_get_name (PyObject *self, void *ignore)
63 {
64  thread_object *thread_obj = (thread_object *) self;
65  char *name;
66 
67  THPY_REQUIRE_VALID (thread_obj);
68 
69  name = thread_obj->thread->name;
70  if (name == NULL)
71  name = target_thread_name (thread_obj->thread);
72 
73  if (name == NULL)
74  Py_RETURN_NONE;
75 
76  return PyString_FromString (name);
77 }
78 
79 static int
80 thpy_set_name (PyObject *self, PyObject *newvalue, void *ignore)
81 {
82  thread_object *thread_obj = (thread_object *) self;
83  char *name;
84 
85  if (! thread_obj->thread)
86  {
87  PyErr_SetString (PyExc_RuntimeError, _("Thread no longer exists."));
88  return -1;
89  }
90 
91  if (newvalue == NULL)
92  {
93  PyErr_SetString (PyExc_TypeError,
94  _("Cannot delete `name' attribute."));
95  return -1;
96  }
97  else if (newvalue == Py_None)
98  name = NULL;
99  else if (! gdbpy_is_string (newvalue))
100  {
101  PyErr_SetString (PyExc_TypeError,
102  _("The value of `name' must be a string."));
103  return -1;
104  }
105  else
106  {
107  name = python_string_to_host_string (newvalue);
108  if (! name)
109  return -1;
110  }
111 
112  xfree (thread_obj->thread->name);
113  thread_obj->thread->name = name;
114 
115  return 0;
116 }
117 
118 static PyObject *
119 thpy_get_num (PyObject *self, void *closure)
120 {
121  thread_object *thread_obj = (thread_object *) self;
122 
123  THPY_REQUIRE_VALID (thread_obj);
124 
125  return PyLong_FromLong (thread_obj->thread->num);
126 }
127 
128 /* Getter for InferiorThread.ptid -> (pid, lwp, tid).
129  Returns a tuple with the thread's ptid components. */
130 
131 static PyObject *
132 thpy_get_ptid (PyObject *self, void *closure)
133 {
134  int pid;
135  long tid, lwp;
136  thread_object *thread_obj = (thread_object *) self;
137 
138  THPY_REQUIRE_VALID (thread_obj);
139 
140  return gdbpy_create_ptid_object (thread_obj->thread->ptid);
141 }
142 
143 /* Implementation of InferiorThread.switch ().
144  Makes this the GDB selected thread. */
145 
146 static PyObject *
147 thpy_switch (PyObject *self, PyObject *args)
148 {
149  thread_object *thread_obj = (thread_object *) self;
150 
151  THPY_REQUIRE_VALID (thread_obj);
152 
153  TRY
154  {
155  switch_to_thread (thread_obj->thread->ptid);
156  }
157  CATCH (except, RETURN_MASK_ALL)
158  {
159  GDB_PY_HANDLE_EXCEPTION (except);
160  }
161  END_CATCH
162 
163  Py_RETURN_NONE;
164 }
165 
166 /* Implementation of InferiorThread.is_stopped () -> Boolean.
167  Return whether the thread is stopped. */
168 
169 static PyObject *
170 thpy_is_stopped (PyObject *self, PyObject *args)
171 {
172  thread_object *thread_obj = (thread_object *) self;
173 
174  THPY_REQUIRE_VALID (thread_obj);
175 
176  if (is_stopped (thread_obj->thread->ptid))
177  Py_RETURN_TRUE;
178 
179  Py_RETURN_FALSE;
180 }
181 
182 /* Implementation of InferiorThread.is_running () -> Boolean.
183  Return whether the thread is running. */
184 
185 static PyObject *
186 thpy_is_running (PyObject *self, PyObject *args)
187 {
188  thread_object *thread_obj = (thread_object *) self;
189 
190  THPY_REQUIRE_VALID (thread_obj);
191 
192  if (is_running (thread_obj->thread->ptid))
193  Py_RETURN_TRUE;
194 
195  Py_RETURN_FALSE;
196 }
197 
198 /* Implementation of InferiorThread.is_exited () -> Boolean.
199  Return whether the thread is exited. */
200 
201 static PyObject *
202 thpy_is_exited (PyObject *self, PyObject *args)
203 {
204  thread_object *thread_obj = (thread_object *) self;
205 
206  THPY_REQUIRE_VALID (thread_obj);
207 
208  if (is_exited (thread_obj->thread->ptid))
209  Py_RETURN_TRUE;
210 
211  Py_RETURN_FALSE;
212 }
213 
214 /* Implementation of gdb.InfThread.is_valid (self) -> Boolean.
215  Returns True if this inferior Thread object still exists
216  in GDB. */
217 
218 static PyObject *
219 thpy_is_valid (PyObject *self, PyObject *args)
220 {
221  thread_object *thread_obj = (thread_object *) self;
222 
223  if (! thread_obj->thread)
224  Py_RETURN_FALSE;
225 
226  Py_RETURN_TRUE;
227 }
228 
229 /* Return a reference to a new Python object representing a ptid_t.
230  The object is a tuple containing (pid, lwp, tid). */
231 PyObject *
233 {
234  int pid;
235  long tid, lwp;
236  PyObject *ret;
237 
238  ret = PyTuple_New (3);
239  if (!ret)
240  return NULL;
241 
242  pid = ptid_get_pid (ptid);
243  lwp = ptid_get_lwp (ptid);
244  tid = ptid_get_tid (ptid);
245 
246  PyTuple_SET_ITEM (ret, 0, PyInt_FromLong (pid));
247  PyTuple_SET_ITEM (ret, 1, PyInt_FromLong (lwp));
248  PyTuple_SET_ITEM (ret, 2, PyInt_FromLong (tid));
249 
250  return ret;
251 }
252 
253 /* Implementation of gdb.selected_thread () -> gdb.InferiorThread.
254  Returns the selected thread object. */
255 
256 PyObject *
257 gdbpy_selected_thread (PyObject *self, PyObject *args)
258 {
259  PyObject *thread_obj;
260 
261  thread_obj = (PyObject *) find_thread_object (inferior_ptid);
262  if (thread_obj)
263  {
264  Py_INCREF (thread_obj);
265  return thread_obj;
266  }
267 
268  Py_RETURN_NONE;
269 }
270 
271 int
273 {
274  if (PyType_Ready (&thread_object_type) < 0)
275  return -1;
276 
277  return gdb_pymodule_addobject (gdb_module, "InferiorThread",
278  (PyObject *) &thread_object_type);
279 }
280 
281 static PyGetSetDef thread_object_getset[] =
282 {
283  { "name", thpy_get_name, thpy_set_name,
284  "The name of the thread, as set by the user or the OS.", NULL },
285  { "num", thpy_get_num, NULL, "ID of the thread, as assigned by GDB.", NULL },
286  { "ptid", thpy_get_ptid, NULL, "ID of the thread, as assigned by the OS.",
287  NULL },
288 
289  { NULL }
290 };
291 
292 static PyMethodDef thread_object_methods[] =
293 {
294  { "is_valid", thpy_is_valid, METH_NOARGS,
295  "is_valid () -> Boolean.\n\
296 Return true if this inferior thread is valid, false if not." },
297  { "switch", thpy_switch, METH_NOARGS,
298  "switch ()\n\
299 Makes this the GDB selected thread." },
300  { "is_stopped", thpy_is_stopped, METH_NOARGS,
301  "is_stopped () -> Boolean\n\
302 Return whether the thread is stopped." },
303  { "is_running", thpy_is_running, METH_NOARGS,
304  "is_running () -> Boolean\n\
305 Return whether the thread is running." },
306  { "is_exited", thpy_is_exited, METH_NOARGS,
307  "is_exited () -> Boolean\n\
308 Return whether the thread is exited." },
309 
310  { NULL }
311 };
312 
313 PyTypeObject thread_object_type =
314 {
315  PyVarObject_HEAD_INIT (NULL, 0)
316  "gdb.InferiorThread", /*tp_name*/
317  sizeof (thread_object), /*tp_basicsize*/
318  0, /*tp_itemsize*/
319  thpy_dealloc, /*tp_dealloc*/
320  0, /*tp_print*/
321  0, /*tp_getattr*/
322  0, /*tp_setattr*/
323  0, /*tp_compare*/
324  0, /*tp_repr*/
325  0, /*tp_as_number*/
326  0, /*tp_as_sequence*/
327  0, /*tp_as_mapping*/
328  0, /*tp_hash */
329  0, /*tp_call*/
330  0, /*tp_str*/
331  0, /*tp_getattro*/
332  0, /*tp_setattro*/
333  0, /*tp_as_buffer*/
334  Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/
335  "GDB thread object", /* tp_doc */
336  0, /* tp_traverse */
337  0, /* tp_clear */
338  0, /* tp_richcompare */
339  0, /* tp_weaklistoffset */
340  0, /* tp_iter */
341  0, /* tp_iternext */
342  thread_object_methods, /* tp_methods */
343  0, /* tp_members */
344  thread_object_getset, /* tp_getset */
345  0, /* tp_base */
346  0, /* tp_dict */
347  0, /* tp_descr_get */
348  0, /* tp_descr_set */
349  0, /* tp_dictoffset */
350  0, /* tp_init */
351  0 /* tp_alloc */
352 };
int gdb_pymodule_addobject(PyObject *module, const char *name, PyObject *object)
Definition: py-utils.c:437
static PyObject * thpy_is_exited(PyObject *self, PyObject *args)
Definition: py-infthread.c:202
#define Py_DECREF(op)
int gdbpy_initialize_thread(void)
Definition: py-infthread.c:272
PyTypeObject thread_object_type
Definition: py-infthread.c:313
static PyMethodDef thread_object_methods[]
Definition: py-infthread.c:292
static PyObject * thpy_get_num(PyObject *self, void *closure)
Definition: py-infthread.c:119
void xfree(void *)
Definition: common-utils.c:97
static PyObject * thpy_is_valid(PyObject *self, PyObject *args)
Definition: py-infthread.c:219
thread_object * create_thread_object(struct thread_info *tp)
Definition: py-infthread.c:40
int gdbpy_is_string(PyObject *obj)
Definition: py-utils.c:228
void switch_to_thread(ptid_t ptid)
Definition: thread.c:1185
char * target_thread_name(struct thread_info *info)
Definition: target.c:2239
#define _(String)
Definition: gdb_locale.h:40
#define END_CATCH
static PyGetSetDef thread_object_getset[]
Definition: py-infthread.c:281
PyObject * inf_obj
static PyObject * thpy_get_ptid(PyObject *self, void *closure)
Definition: py-infthread.c:132
Definition: ptid.h:35
char * name
Definition: gdbthread.h:176
#define GDB_PY_HANDLE_EXCEPTION(Exception)
#define TRY
const char *const name
Definition: aarch64-tdep.c:68
PyObject * gdbpy_create_ptid_object(ptid_t ptid)
Definition: py-infthread.c:232
int is_stopped(ptid_t ptid)
Definition: thread.c:822
#define CATCH(EXCEPTION, MASK)
thread_object * find_thread_object(ptid_t ptid)
Definition: py-inferior.c:280
char * python_string_to_host_string(PyObject *obj)
Definition: py-utils.c:210
static PyObject * thpy_is_running(PyObject *self, PyObject *args)
Definition: py-infthread.c:186
#define THPY_REQUIRE_VALID(Thread)
Definition: py-infthread.c:29
PyObject * gdbpy_selected_thread(PyObject *self, PyObject *args)
Definition: py-infthread.c:257
PyObject_HEAD struct thread_info * thread
int ptid_get_pid(ptid_t ptid)
Definition: ptid.c:52
static PyObject * thpy_is_stopped(PyObject *self, PyObject *args)
Definition: py-infthread.c:170
long ptid_get_tid(ptid_t ptid)
Definition: ptid.c:68
PyTypeObject thread_object_type CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF("thread_object")
ptid_t ptid
Definition: gdbthread.h:169
PyObject * find_inferior_object(int pid)
Definition: py-inferior.c:269
static int thpy_set_name(PyObject *self, PyObject *newvalue, void *ignore)
Definition: py-infthread.c:80
ptid_t inferior_ptid
Definition: infcmd.c:124
static PyObject * thpy_switch(PyObject *self, PyObject *args)
Definition: py-infthread.c:147
static void thpy_dealloc(PyObject *self)
Definition: py-infthread.c:55
int is_exited(ptid_t ptid)
Definition: thread.c:828
static int ignore(struct target_ops *ops, struct gdbarch *gdbarch, struct bp_target_info *bp_tgt)
Definition: corelow.c:917
long ptid_get_lwp(ptid_t ptid)
Definition: ptid.c:60
PyObject * gdb_module
Definition: python.c:112
static PyObject * thpy_get_name(PyObject *self, void *ignore)
Definition: py-infthread.c:62
int is_running(ptid_t ptid)
Definition: thread.c:834
mach_port_t mach_port_t name mach_port_t mach_port_t name error_t int int rusage_t pid_t pid
Definition: gnu-nat.c:1818
#define Py_TYPE(ob)
#define PyVarObject_HEAD_INIT(type, size)