GDB (API)
|
00001 /* Python interface to inferior threads. 00002 00003 Copyright (C) 2009-2013 Free Software Foundation, Inc. 00004 00005 This file is part of GDB. 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 3 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program. If not, see <http://www.gnu.org/licenses/>. */ 00019 00020 #include "defs.h" 00021 #include "exceptions.h" 00022 #include "gdbthread.h" 00023 #include "inferior.h" 00024 #include "python-internal.h" 00025 00026 static PyTypeObject thread_object_type 00027 CPYCHECKER_TYPE_OBJECT_FOR_TYPEDEF ("thread_object"); 00028 00029 /* Require that INFERIOR be a valid inferior ID. */ 00030 #define THPY_REQUIRE_VALID(Thread) \ 00031 do { \ 00032 if (!Thread->thread) \ 00033 { \ 00034 PyErr_SetString (PyExc_RuntimeError, \ 00035 _("Thread no longer exists.")); \ 00036 return NULL; \ 00037 } \ 00038 } while (0) 00039 00040 00041 00042 thread_object * 00043 create_thread_object (struct thread_info *tp) 00044 { 00045 thread_object *thread_obj; 00046 00047 thread_obj = PyObject_New (thread_object, &thread_object_type); 00048 if (!thread_obj) 00049 return NULL; 00050 00051 thread_obj->thread = tp; 00052 thread_obj->inf_obj = find_inferior_object (ptid_get_pid (tp->ptid)); 00053 00054 return thread_obj; 00055 } 00056 00057 00058 00059 static void 00060 thpy_dealloc (PyObject *self) 00061 { 00062 Py_DECREF (((thread_object *) self)->inf_obj); 00063 Py_TYPE (self)->tp_free (self); 00064 } 00065 00066 static PyObject * 00067 thpy_get_name (PyObject *self, void *ignore) 00068 { 00069 thread_object *thread_obj = (thread_object *) self; 00070 char *name; 00071 00072 THPY_REQUIRE_VALID (thread_obj); 00073 00074 name = thread_obj->thread->name; 00075 if (name == NULL) 00076 name = target_thread_name (thread_obj->thread); 00077 00078 if (name == NULL) 00079 Py_RETURN_NONE; 00080 00081 return PyString_FromString (name); 00082 } 00083 00084 static int 00085 thpy_set_name (PyObject *self, PyObject *newvalue, void *ignore) 00086 { 00087 thread_object *thread_obj = (thread_object *) self; 00088 char *name; 00089 00090 if (! thread_obj->thread) 00091 { 00092 PyErr_SetString (PyExc_RuntimeError, _("Thread no longer exists.")); 00093 return -1; 00094 } 00095 00096 if (newvalue == NULL) 00097 { 00098 PyErr_SetString (PyExc_TypeError, 00099 _("Cannot delete `name' attribute.")); 00100 return -1; 00101 } 00102 else if (newvalue == Py_None) 00103 name = NULL; 00104 else if (! gdbpy_is_string (newvalue)) 00105 { 00106 PyErr_SetString (PyExc_TypeError, 00107 _("The value of `name' must be a string.")); 00108 return -1; 00109 } 00110 else 00111 { 00112 name = python_string_to_host_string (newvalue); 00113 if (! name) 00114 return -1; 00115 } 00116 00117 xfree (thread_obj->thread->name); 00118 thread_obj->thread->name = name; 00119 00120 return 0; 00121 } 00122 00123 static PyObject * 00124 thpy_get_num (PyObject *self, void *closure) 00125 { 00126 thread_object *thread_obj = (thread_object *) self; 00127 00128 THPY_REQUIRE_VALID (thread_obj); 00129 00130 return PyLong_FromLong (thread_obj->thread->num); 00131 } 00132 00133 /* Getter for InferiorThread.ptid -> (pid, lwp, tid). 00134 Returns a tuple with the thread's ptid components. */ 00135 static PyObject * 00136 thpy_get_ptid (PyObject *self, void *closure) 00137 { 00138 int pid; 00139 long tid, lwp; 00140 thread_object *thread_obj = (thread_object *) self; 00141 PyObject *ret; 00142 00143 THPY_REQUIRE_VALID (thread_obj); 00144 00145 ret = PyTuple_New (3); 00146 if (!ret) 00147 return NULL; 00148 00149 pid = ptid_get_pid (thread_obj->thread->ptid); 00150 lwp = ptid_get_lwp (thread_obj->thread->ptid); 00151 tid = ptid_get_tid (thread_obj->thread->ptid); 00152 00153 PyTuple_SET_ITEM (ret, 0, PyInt_FromLong (pid)); 00154 PyTuple_SET_ITEM (ret, 1, PyInt_FromLong (lwp)); 00155 PyTuple_SET_ITEM (ret, 2, PyInt_FromLong (tid)); 00156 00157 return ret; 00158 } 00159 00160 /* Implementation of InferiorThread.switch (). 00161 Makes this the GDB selected thread. */ 00162 static PyObject * 00163 thpy_switch (PyObject *self, PyObject *args) 00164 { 00165 thread_object *thread_obj = (thread_object *) self; 00166 volatile struct gdb_exception except; 00167 00168 THPY_REQUIRE_VALID (thread_obj); 00169 00170 TRY_CATCH (except, RETURN_MASK_ALL) 00171 { 00172 switch_to_thread (thread_obj->thread->ptid); 00173 } 00174 GDB_PY_HANDLE_EXCEPTION (except); 00175 00176 Py_RETURN_NONE; 00177 } 00178 00179 /* Implementation of InferiorThread.is_stopped () -> Boolean. 00180 Return whether the thread is stopped. */ 00181 static PyObject * 00182 thpy_is_stopped (PyObject *self, PyObject *args) 00183 { 00184 thread_object *thread_obj = (thread_object *) self; 00185 00186 THPY_REQUIRE_VALID (thread_obj); 00187 00188 if (is_stopped (thread_obj->thread->ptid)) 00189 Py_RETURN_TRUE; 00190 00191 Py_RETURN_FALSE; 00192 } 00193 00194 /* Implementation of InferiorThread.is_running () -> Boolean. 00195 Return whether the thread is running. */ 00196 static PyObject * 00197 thpy_is_running (PyObject *self, PyObject *args) 00198 { 00199 thread_object *thread_obj = (thread_object *) self; 00200 00201 THPY_REQUIRE_VALID (thread_obj); 00202 00203 if (is_running (thread_obj->thread->ptid)) 00204 Py_RETURN_TRUE; 00205 00206 Py_RETURN_FALSE; 00207 } 00208 00209 /* Implementation of InferiorThread.is_exited () -> Boolean. 00210 Return whether the thread is exited. */ 00211 static PyObject * 00212 thpy_is_exited (PyObject *self, PyObject *args) 00213 { 00214 thread_object *thread_obj = (thread_object *) self; 00215 00216 THPY_REQUIRE_VALID (thread_obj); 00217 00218 if (is_exited (thread_obj->thread->ptid)) 00219 Py_RETURN_TRUE; 00220 00221 Py_RETURN_FALSE; 00222 } 00223 00224 /* Implementation of gdb.InfThread.is_valid (self) -> Boolean. 00225 Returns True if this inferior Thread object still exists 00226 in GDB. */ 00227 00228 static PyObject * 00229 thpy_is_valid (PyObject *self, PyObject *args) 00230 { 00231 thread_object *thread_obj = (thread_object *) self; 00232 00233 if (! thread_obj->thread) 00234 Py_RETURN_FALSE; 00235 00236 Py_RETURN_TRUE; 00237 } 00238 00239 /* Implementation of gdb.selected_thread () -> gdb.InferiorThread. 00240 Returns the selected thread object. */ 00241 PyObject * 00242 gdbpy_selected_thread (PyObject *self, PyObject *args) 00243 { 00244 PyObject *thread_obj; 00245 00246 thread_obj = (PyObject *) find_thread_object (inferior_ptid); 00247 if (thread_obj) 00248 { 00249 Py_INCREF (thread_obj); 00250 return thread_obj; 00251 } 00252 00253 Py_RETURN_NONE; 00254 } 00255 00256 00257 00258 int 00259 gdbpy_initialize_thread (void) 00260 { 00261 if (PyType_Ready (&thread_object_type) < 0) 00262 return -1; 00263 00264 return gdb_pymodule_addobject (gdb_module, "InferiorThread", 00265 (PyObject *) &thread_object_type); 00266 } 00267 00268 00269 00270 static PyGetSetDef thread_object_getset[] = 00271 { 00272 { "name", thpy_get_name, thpy_set_name, 00273 "The name of the thread, as set by the user or the OS.", NULL }, 00274 { "num", thpy_get_num, NULL, "ID of the thread, as assigned by GDB.", NULL }, 00275 { "ptid", thpy_get_ptid, NULL, "ID of the thread, as assigned by the OS.", 00276 NULL }, 00277 00278 { NULL } 00279 }; 00280 00281 static PyMethodDef thread_object_methods[] = 00282 { 00283 { "is_valid", thpy_is_valid, METH_NOARGS, 00284 "is_valid () -> Boolean.\n\ 00285 Return true if this inferior thread is valid, false if not." }, 00286 { "switch", thpy_switch, METH_NOARGS, 00287 "switch ()\n\ 00288 Makes this the GDB selected thread." }, 00289 { "is_stopped", thpy_is_stopped, METH_NOARGS, 00290 "is_stopped () -> Boolean\n\ 00291 Return whether the thread is stopped." }, 00292 { "is_running", thpy_is_running, METH_NOARGS, 00293 "is_running () -> Boolean\n\ 00294 Return whether the thread is running." }, 00295 { "is_exited", thpy_is_exited, METH_NOARGS, 00296 "is_exited () -> Boolean\n\ 00297 Return whether the thread is exited." }, 00298 00299 { NULL } 00300 }; 00301 00302 static PyTypeObject thread_object_type = 00303 { 00304 PyVarObject_HEAD_INIT (NULL, 0) 00305 "gdb.InferiorThread", /*tp_name*/ 00306 sizeof (thread_object), /*tp_basicsize*/ 00307 0, /*tp_itemsize*/ 00308 thpy_dealloc, /*tp_dealloc*/ 00309 0, /*tp_print*/ 00310 0, /*tp_getattr*/ 00311 0, /*tp_setattr*/ 00312 0, /*tp_compare*/ 00313 0, /*tp_repr*/ 00314 0, /*tp_as_number*/ 00315 0, /*tp_as_sequence*/ 00316 0, /*tp_as_mapping*/ 00317 0, /*tp_hash */ 00318 0, /*tp_call*/ 00319 0, /*tp_str*/ 00320 0, /*tp_getattro*/ 00321 0, /*tp_setattro*/ 00322 0, /*tp_as_buffer*/ 00323 Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_ITER, /*tp_flags*/ 00324 "GDB thread object", /* tp_doc */ 00325 0, /* tp_traverse */ 00326 0, /* tp_clear */ 00327 0, /* tp_richcompare */ 00328 0, /* tp_weaklistoffset */ 00329 0, /* tp_iter */ 00330 0, /* tp_iternext */ 00331 thread_object_methods, /* tp_methods */ 00332 0, /* tp_members */ 00333 thread_object_getset, /* tp_getset */ 00334 0, /* tp_base */ 00335 0, /* tp_dict */ 00336 0, /* tp_descr_get */ 00337 0, /* tp_descr_set */ 00338 0, /* tp_dictoffset */ 00339 0, /* tp_init */ 00340 0 /* tp_alloc */ 00341 };