gdb/python/py-infthread.c - gdb

Global variables defined

Functions defined

Macros defined

Source code

  1. /* Python interface to inferior threads.

  2.    Copyright (C) 2009-2015 Free Software Foundation, Inc.

  3.    This file is part of GDB.

  4.    This program is free software; you can redistribute it and/or modify
  5.    it under the terms of the GNU General Public License as published by
  6.    the Free Software Foundation; either version 3 of the License, or
  7.    (at your option) any later version.

  8.    This program is distributed in the hope that it will be useful,
  9.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  10.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  11.    GNU General Public License for more details.

  12.    You should have received a copy of the GNU General Public License
  13.    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */

  14. #include "defs.h"
  15. #include "gdbthread.h"
  16. #include "inferior.h"
  17. #include "python-internal.h"

  18. static PyTypeObject thread_object_type
  19.     CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("thread_object");

  20. /* Require that INFERIOR be a valid inferior ID.  */
  21. #define THPY_REQUIRE_VALID(Thread)                                \
  22.   do {                                                                \
  23.     if (!Thread->thread)                                        \
  24.       {                                                                \
  25.         PyErr_SetString (PyExc_RuntimeError,                        \
  26.                          _("Thread no longer exists."));        \
  27.         return NULL;                                                \
  28.       }                                                                \
  29.   } while (0)

  30. thread_object *
  31. create_thread_object (struct thread_info *tp)
  32. {
  33.   thread_object *thread_obj;

  34.   thread_obj = PyObject_New (thread_object, &thread_object_type);
  35.   if (!thread_obj)
  36.     return NULL;

  37.   thread_obj->thread = tp;
  38.   thread_obj->inf_obj = find_inferior_object (ptid_get_pid (tp->ptid));

  39.   return thread_obj;
  40. }

  41. static void
  42. thpy_dealloc (PyObject *self)
  43. {
  44.   Py_DECREF (((thread_object *) self)->inf_obj);
  45.   Py_TYPE (self)->tp_free (self);
  46. }

  47. static PyObject *
  48. thpy_get_name (PyObject *self, void *ignore)
  49. {
  50.   thread_object *thread_obj = (thread_object *) self;
  51.   char *name;

  52.   THPY_REQUIRE_VALID (thread_obj);

  53.   name = thread_obj->thread->name;
  54.   if (name == NULL)
  55.     name = target_thread_name (thread_obj->thread);

  56.   if (name == NULL)
  57.     Py_RETURN_NONE;

  58.   return PyString_FromString (name);
  59. }

  60. static int
  61. thpy_set_name (PyObject *self, PyObject *newvalue, void *ignore)
  62. {
  63.   thread_object *thread_obj = (thread_object *) self;
  64.   char *name;

  65.   if (! thread_obj->thread)
  66.     {
  67.       PyErr_SetString (PyExc_RuntimeError, _("Thread no longer exists."));
  68.       return -1;
  69.     }

  70.   if (newvalue == NULL)
  71.     {
  72.       PyErr_SetString (PyExc_TypeError,
  73.                        _("Cannot delete `name' attribute."));
  74.       return -1;
  75.     }
  76.   else if (newvalue == Py_None)
  77.     name = NULL;
  78.   else if (! gdbpy_is_string (newvalue))
  79.     {
  80.       PyErr_SetString (PyExc_TypeError,
  81.                        _("The value of `name' must be a string."));
  82.       return -1;
  83.     }
  84.   else
  85.     {
  86.       name = python_string_to_host_string (newvalue);
  87.       if (! name)
  88.         return -1;
  89.     }

  90.   xfree (thread_obj->thread->name);
  91.   thread_obj->thread->name = name;

  92.   return 0;
  93. }

  94. static PyObject *
  95. thpy_get_num (PyObject *self, void *closure)
  96. {
  97.   thread_object *thread_obj = (thread_object *) self;

  98.   THPY_REQUIRE_VALID (thread_obj);

  99.   return PyLong_FromLong (thread_obj->thread->num);
  100. }

  101. /* Getter for InferiorThread.ptid  -> (pid, lwp, tid).
  102.    Returns a tuple with the thread's ptid components.  */

  103. static PyObject *
  104. thpy_get_ptid (PyObject *self, void *closure)
  105. {
  106.   int pid;
  107.   long tid, lwp;
  108.   thread_object *thread_obj = (thread_object *) self;

  109.   THPY_REQUIRE_VALID (thread_obj);

  110.   return gdbpy_create_ptid_object (thread_obj->thread->ptid);
  111. }

  112. /* Implementation of InferiorThread.switch ().
  113.    Makes this the GDB selected thread.  */

  114. static PyObject *
  115. thpy_switch (PyObject *self, PyObject *args)
  116. {
  117.   thread_object *thread_obj = (thread_object *) self;
  118.   volatile struct gdb_exception except;

  119.   THPY_REQUIRE_VALID (thread_obj);

  120.   TRY_CATCH (except, RETURN_MASK_ALL)
  121.     {
  122.       switch_to_thread (thread_obj->thread->ptid);
  123.     }
  124.   GDB_PY_HANDLE_EXCEPTION (except);

  125.   Py_RETURN_NONE;
  126. }

  127. /* Implementation of InferiorThread.is_stopped () -> Boolean.
  128.    Return whether the thread is stopped.  */

  129. static PyObject *
  130. thpy_is_stopped (PyObject *self, PyObject *args)
  131. {
  132.   thread_object *thread_obj = (thread_object *) self;

  133.   THPY_REQUIRE_VALID (thread_obj);

  134.   if (is_stopped (thread_obj->thread->ptid))
  135.     Py_RETURN_TRUE;

  136.   Py_RETURN_FALSE;
  137. }

  138. /* Implementation of InferiorThread.is_running () -> Boolean.
  139.    Return whether the thread is running.  */

  140. static PyObject *
  141. thpy_is_running (PyObject *self, PyObject *args)
  142. {
  143.   thread_object *thread_obj = (thread_object *) self;

  144.   THPY_REQUIRE_VALID (thread_obj);

  145.   if (is_running (thread_obj->thread->ptid))
  146.     Py_RETURN_TRUE;

  147.   Py_RETURN_FALSE;
  148. }

  149. /* Implementation of InferiorThread.is_exited () -> Boolean.
  150.    Return whether the thread is exited.  */

  151. static PyObject *
  152. thpy_is_exited (PyObject *self, PyObject *args)
  153. {
  154.   thread_object *thread_obj = (thread_object *) self;

  155.   THPY_REQUIRE_VALID (thread_obj);

  156.   if (is_exited (thread_obj->thread->ptid))
  157.     Py_RETURN_TRUE;

  158.   Py_RETURN_FALSE;
  159. }

  160. /* Implementation of gdb.InfThread.is_valid (self) -> Boolean.
  161.    Returns True if this inferior Thread object still exists
  162.    in GDB.  */

  163. static PyObject *
  164. thpy_is_valid (PyObject *self, PyObject *args)
  165. {
  166.   thread_object *thread_obj = (thread_object *) self;

  167.   if (! thread_obj->thread)
  168.     Py_RETURN_FALSE;

  169.   Py_RETURN_TRUE;
  170. }

  171. /* Return a reference to a new Python object representing a ptid_t.
  172.    The object is a tuple containing (pid, lwp, tid). */
  173. PyObject *
  174. gdbpy_create_ptid_object (ptid_t ptid)
  175. {
  176.   int pid;
  177.   long tid, lwp;
  178.   PyObject *ret;

  179.   ret = PyTuple_New (3);
  180.   if (!ret)
  181.     return NULL;

  182.   pid = ptid_get_pid (ptid);
  183.   lwp = ptid_get_lwp (ptid);
  184.   tid = ptid_get_tid (ptid);

  185.   PyTuple_SET_ITEM (ret, 0, PyInt_FromLong (pid));
  186.   PyTuple_SET_ITEM (ret, 1, PyInt_FromLong (lwp));
  187.   PyTuple_SET_ITEM (ret, 2, PyInt_FromLong (tid));

  188.   return ret;
  189. }

  190. /* Implementation of gdb.selected_thread () -> gdb.InferiorThread.
  191.    Returns the selected thread object.  */

  192. PyObject *
  193. gdbpy_selected_thread (PyObject *self, PyObject *args)
  194. {
  195.   PyObject *thread_obj;

  196.   thread_obj = (PyObject *) find_thread_object (inferior_ptid);
  197.   if (thread_obj)
  198.     {
  199.       Py_INCREF (thread_obj);
  200.       return thread_obj;
  201.     }

  202.   Py_RETURN_NONE;
  203. }

  204. int
  205. gdbpy_initialize_thread (void)
  206. {
  207.   if (PyType_Ready (&thread_object_type) < 0)
  208.     return -1;

  209.   return gdb_pymodule_addobject (gdb_module, "InferiorThread",
  210.                                  (PyObject *) &thread_object_type);
  211. }

  212. static PyGetSetDef thread_object_getset[] =
  213. {
  214.   { "name", thpy_get_name, thpy_set_name,
  215.     "The name of the thread, as set by the user or the OS.", NULL },
  216.   { "num", thpy_get_num, NULL, "ID of the thread, as assigned by GDB.", NULL },
  217.   { "ptid", thpy_get_ptid, NULL, "ID of the thread, as assigned by the OS.",
  218.     NULL },

  219.   { NULL }
  220. };

  221. static PyMethodDef thread_object_methods[] =
  222. {
  223.   { "is_valid", thpy_is_valid, METH_NOARGS,
  224.     "is_valid () -> Boolean.\n\
  225. Return true if this inferior thread is valid, false if not." },
  226.   { "switch", thpy_switch, METH_NOARGS,
  227.     "switch ()\n\
  228. Makes this the GDB selected thread." },
  229.   { "is_stopped", thpy_is_stopped, METH_NOARGS,
  230.     "is_stopped () -> Boolean\n\
  231. Return whether the thread is stopped." },
  232.   { "is_running", thpy_is_running, METH_NOARGS,
  233.     "is_running () -> Boolean\n\
  234. Return whether the thread is running." },
  235.   { "is_exited", thpy_is_exited, METH_NOARGS,
  236.     "is_exited () -> Boolean\n\
  237. Return whether the thread is exited." },

  238.   { NULL }
  239. };

  240. static PyTypeObject thread_object_type =
  241. {
  242.   PyVarObject_HEAD_INIT (NULL, 0)
  243.   "gdb.InferiorThread",                  /*tp_name*/
  244.   sizeof (thread_object),          /*tp_basicsize*/
  245.   0,                                  /*tp_itemsize*/
  246.   thpy_dealloc,                          /*tp_dealloc*/
  247.   0,                                  /*tp_print*/
  248.   0,                                  /*tp_getattr*/
  249.   0,                                  /*tp_setattr*/
  250.   0,                                  /*tp_compare*/
  251.   0,                                  /*tp_repr*/
  252.   0,                                  /*tp_as_number*/
  253.   0,                                  /*tp_as_sequence*/
  254.   0,                                  /*tp_as_mapping*/
  255.   0,                                  /*tp_hash */
  256.   0,                                  /*tp_call*/
  257.   0,                                  /*tp_str*/
  258.   0,                                  /*tp_getattro*/
  259.   0,                                  /*tp_setattro*/
  260.   0,                                  /*tp_as_buffer*/
  261.   Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER/*tp_flags*/
  262.   "GDB thread object",                  /* tp_doc */
  263.   0,                                  /* tp_traverse */
  264.   0,                                  /* tp_clear */
  265.   0,                                  /* tp_richcompare */
  266.   0,                                  /* tp_weaklistoffset */
  267.   0,                                  /* tp_iter */
  268.   0,                                  /* tp_iternext */
  269.   thread_object_methods,          /* tp_methods */
  270.   0,                                  /* tp_members */
  271.   thread_object_getset,                  /* tp_getset */
  272.   0,                                  /* tp_base */
  273.   0,                                  /* tp_dict */
  274.   0,                                  /* tp_descr_get */
  275.   0,                                  /* tp_descr_set */
  276.   0,                                  /* tp_dictoffset */
  277.   0,                                  /* tp_init */
  278.   0                                  /* tp_alloc */
  279. };