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 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
// Copyright (c) Meta Platforms, Inc. and affiliates.
// SPDX-License-Identifier: LGPL-2.1-or-later
#include "drgnpy.h"
#include "../program.h"
#include "../util.h"
static Program *Thread_prog(Thread *self)
{
return container_of(self->thread.prog, Program, prog);
}
PyObject *Thread_wrap(struct drgn_thread *thread)
{
_cleanup_pydecref_ Thread *ret = call_tp_alloc(Thread);
if (!ret)
return NULL;
struct drgn_error *err =
drgn_thread_dup_internal(thread, &ret->thread);
if (err) {
ret->thread.prog = NULL;
return set_drgn_error(err);
}
Py_INCREF(container_of(thread->prog, Program, prog));
return (PyObject *)no_cleanup_ptr(ret);
}
static void Thread_dealloc(Thread *self)
{
PyObject_GC_UnTrack(self);
if (self->thread.prog) {
Program *prog = Thread_prog(self);
drgn_thread_deinit(&self->thread);
Py_DECREF(prog);
}
Py_TYPE(self)->tp_free((PyObject *)self);
}
static int Thread_traverse(Thread *self, visitproc visit, void *arg)
{
if (self->thread.prog)
Py_VISIT(Thread_prog(self));
return 0;
}
static PyObject *Thread_get_tid(Thread *self)
{
return PyLong_FromUint32(self->thread.tid);
}
static DrgnObject *Thread_get_object(Thread *self)
{
const struct drgn_object *object;
struct drgn_error *err = drgn_thread_object(&self->thread, &object);
if (err)
return set_drgn_error(err);
_cleanup_pydecref_ DrgnObject *ret =
DrgnObject_alloc(Thread_prog(self));
if (!ret)
return NULL;
err = drgn_object_copy(&ret->obj, object);
if (err)
return set_drgn_error(err);
return_ptr(ret);
}
static PyObject *Thread_get_name(Thread *self)
{
_cleanup_free_ char *ret = NULL;
struct drgn_error *err = drgn_thread_name(&self->thread, &ret);
if (err)
return set_drgn_error(err);
if (!ret) {
Py_RETURN_NONE;
}
return PyUnicode_DecodeFSDefault(ret);
}
static PyObject *Thread_stack_trace(Thread *self)
{
struct drgn_error *err;
struct drgn_stack_trace *trace;
err = drgn_thread_stack_trace(&self->thread, &trace);
if (err)
return set_drgn_error(err);
PyObject *ret = StackTrace_wrap(trace);
if (!ret)
drgn_stack_trace_destroy(trace);
return ret;
}
static PyGetSetDef Thread_getset[] = {
{"tid", (getter)Thread_get_tid, NULL, drgn_Thread_tid_DOC},
{"object", (getter)Thread_get_object, NULL, drgn_Thread_object_DOC},
{"name", (getter)Thread_get_name, NULL, drgn_Thread_name_DOC},
{},
};
static PyMethodDef Thread_methods[] = {
{"stack_trace", (PyCFunction)Thread_stack_trace, METH_NOARGS,
drgn_Thread_stack_trace_DOC},
{},
};
PyTypeObject Thread_type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "_drgn.Thread",
.tp_basicsize = sizeof(Thread),
.tp_dealloc = (destructor)Thread_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_doc = drgn_Thread_DOC,
.tp_traverse = (traverseproc)Thread_traverse,
.tp_getset = Thread_getset,
.tp_methods = Thread_methods,
};
static void ThreadIterator_dealloc(ThreadIterator *self)
{
PyObject_GC_UnTrack(self);
drgn_thread_iterator_destroy(self->iterator);
Py_XDECREF(self->prog);
Py_TYPE(self)->tp_free((PyObject *)self);
}
static int ThreadIterator_traverse(ThreadIterator *self, visitproc visit,
void *arg)
{
Py_VISIT(self->prog);
return 0;
}
static PyObject *ThreadIterator_next(ThreadIterator *self)
{
struct drgn_error *err;
struct drgn_thread *thread;
err = drgn_thread_iterator_next(self->iterator, &thread);
if (err)
return set_drgn_error(err);
return thread ? Thread_wrap(thread) : NULL;
}
PyTypeObject ThreadIterator_type = {
PyVarObject_HEAD_INIT(NULL, 0)
.tp_name = "_drgn._ThreadIterator",
.tp_basicsize = sizeof(ThreadIterator),
.tp_dealloc = (destructor)ThreadIterator_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
.tp_traverse = (traverseproc)ThreadIterator_traverse,
.tp_iter = PyObject_SelfIter,
.tp_iternext = (iternextfunc)ThreadIterator_next,
};
|