[SATYR PATCHv2 3/6] python: base classes for threads and stacktraces
Martin Milata
mmilata at redhat.com
Mon Jun 24 09:30:08 UTC 2013
Similar to previous commit, base classes were added that are
superclasses of thread and stacktrace classes. The situation is a bit
more complicated here:
BaseThread: methods for all thread types
SingleThreadStacktrace: subclass of BaseThread, base class for
stacktraces that have only one thread and can be treated as one
MultiThreadStacktrace: base class for stacktrace types that can contain
multiple threads
Signed-off-by: Martin Milata <mmilata at redhat.com>
---
python/Makefile.am | 4 +
python/py_base_stacktrace.c | 293 ++++++++++++++++++++++++++++++++++++++++++
python/py_base_stacktrace.h | 64 +++++++++
python/py_base_thread.c | 205 +++++++++++++++++++++++++++++
python/py_base_thread.h | 56 ++++++++
python/py_gdb_stacktrace.c | 94 ++++++--------
python/py_gdb_stacktrace.h | 9 +-
python/py_gdb_thread.c | 161 +++--------------------
python/py_gdb_thread.h | 14 +-
python/py_java_stacktrace.c | 147 +++------------------
python/py_java_stacktrace.h | 10 +-
python/py_java_thread.c | 130 ++-----------------
python/py_java_thread.h | 14 +-
python/py_koops_stacktrace.c | 141 ++------------------
python/py_koops_stacktrace.h | 7 +-
python/py_module.c | 20 +++
python/py_python_stacktrace.c | 135 ++-----------------
python/py_python_stacktrace.h | 7 +-
18 files changed, 777 insertions(+), 734 deletions(-)
create mode 100644 python/py_base_stacktrace.c
create mode 100644 python/py_base_stacktrace.h
create mode 100644 python/py_base_thread.c
create mode 100644 python/py_base_thread.h
diff --git a/python/Makefile.am b/python/Makefile.am
index 49ef936..12f408f 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -10,6 +10,10 @@ _satyr_la_SOURCES = \
py_cluster.c \
py_base_frame.h \
py_base_frame.c \
+ py_base_thread.h \
+ py_base_thread.c \
+ py_base_stacktrace.h \
+ py_base_stacktrace.c \
py_gdb_frame.h \
py_gdb_frame.c \
py_gdb_sharedlib.h \
diff --git a/python/py_base_stacktrace.c b/python/py_base_stacktrace.c
new file mode 100644
index 0000000..c729335
--- /dev/null
+++ b/python/py_base_stacktrace.c
@@ -0,0 +1,293 @@
+/*
+ py_base_stacktrace.c
+
+ Copyright (C) 2013 Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+
+#include "py_base_thread.h"
+#include "py_base_stacktrace.h"
+
+#include "stacktrace.h"
+#include "thread.h"
+
+#define single_stacktrace_doc "satyr.SingleThreadStacktrace - base class for stacktrace with single thread"
+#define multi_stacktrace_doc "satyr.MultiThreadStacktrace - base class for stacktrace with multiple threads"
+
+#define to_short_text_doc "Usage: stacktrace.to_short_text([max_frames])\n" \
+ "Returns short text representation of the stacktrace. If max_frames is\n" \
+ "specified, the result includes only that much topmost frames.\n"
+
+#define threads_doc "A list containing the objects representing threads in the stacktrace."
+
+static PyMethodDef
+single_methods[] =
+{
+ { "to_short_text", sr_py_single_stacktrace_to_short_text, METH_VARARGS, to_short_text_doc },
+ { NULL },
+};
+
+PyTypeObject sr_py_single_stacktrace_type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "satyr.SingleThreadStacktrace", /* tp_name */
+ sizeof(struct sr_py_base_thread), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ NULL, /* tp_dealloc */
+ NULL, /* tp_print */
+ NULL, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL, /* tp_hash */
+ NULL, /* tp_call */
+ NULL, /* tp_str */
+ NULL, /* tp_getattro */
+ NULL, /* tp_setattro */
+ NULL, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ single_stacktrace_doc, /* tp_doc */
+ NULL, /* tp_traverse */
+ NULL, /* tp_clear */
+ NULL, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ NULL, /* tp_iter */
+ NULL, /* tp_iternext */
+ single_methods, /* tp_methods */
+ NULL, /* tp_members */
+ NULL, /* tp_getset */
+ &sr_py_base_thread_type, /* tp_base */
+ NULL, /* tp_dict */
+ NULL, /* tp_descr_get */
+ NULL, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ NULL, /* tp_init */
+ NULL, /* tp_alloc */
+ NULL, /* tp_new */
+ NULL, /* tp_free */
+ NULL, /* tp_is_gc */
+ NULL, /* tp_bases */
+ NULL, /* tp_mro */
+ NULL, /* tp_cache */
+ NULL, /* tp_subclasses */
+ NULL, /* tp_weaklist */
+};
+
+static PyMemberDef
+multi_members[] =
+{
+ { (char *)"threads", T_OBJECT_EX, offsetof(struct sr_py_multi_stacktrace, threads), 0, (char *)threads_doc },
+ { NULL },
+};
+
+static PyMethodDef
+multi_methods[] =
+{
+ { "to_short_text", sr_py_multi_stacktrace_to_short_text, METH_VARARGS, to_short_text_doc },
+ { NULL },
+};
+
+PyTypeObject sr_py_multi_stacktrace_type = {
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "satyr.MultiThreadStacktrace", /* tp_name */
+ sizeof(struct sr_py_multi_stacktrace), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ NULL, /* tp_dealloc */
+ NULL, /* tp_print */
+ NULL, /* tp_getattr */
+ NULL, /* tp_setattr */
+ NULL, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL, /* tp_hash */
+ NULL, /* tp_call */
+ NULL, /* tp_str */
+ NULL, /* tp_getattro */
+ NULL, /* tp_setattro */
+ NULL, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ multi_stacktrace_doc, /* tp_doc */
+ NULL, /* tp_traverse */
+ NULL, /* tp_clear */
+ NULL, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ NULL, /* tp_iter */
+ NULL, /* tp_iternext */
+ multi_methods, /* tp_methods */
+ multi_members, /* tp_members */
+ NULL, /* tp_getset */
+ NULL, /* tp_base */
+ NULL, /* tp_dict */
+ NULL, /* tp_descr_get */
+ NULL, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ NULL, /* tp_init */
+ NULL, /* tp_alloc */
+ NULL, /* tp_new */
+ NULL, /* tp_free */
+ NULL, /* tp_is_gc */
+ NULL, /* tp_bases */
+ NULL, /* tp_mro */
+ NULL, /* tp_cache */
+ NULL, /* tp_subclasses */
+ NULL, /* tp_weaklist */
+};
+
+int
+threads_prepare_linked_list(struct sr_py_multi_stacktrace *stacktrace)
+{
+ int i;
+ PyObject *item;
+ struct sr_py_base_thread *current = NULL, *prev = NULL;
+
+ for (i = 0; i < PyList_Size(stacktrace->threads); ++i)
+ {
+ item = PyList_GetItem(stacktrace->threads, i);
+ if (!item)
+ return -1;
+
+ Py_INCREF(item);
+ if (!PyObject_TypeCheck(item, stacktrace->thread_type))
+ {
+ Py_XDECREF(current);
+ Py_XDECREF(prev);
+ PyErr_Format(PyExc_TypeError,
+ "threads must be a list of %s objects",
+ stacktrace->thread_type->tp_name);
+ return -1;
+ }
+
+ /* Note: this line is not present in frames_prepare_linked_list. */
+ current = (struct sr_py_base_thread*)item;
+ if (frames_prepare_linked_list(current) < 0)
+ return -1;
+
+ if (i == 0)
+ sr_stacktrace_set_threads(stacktrace->stacktrace, current->thread);
+ else
+ sr_thread_set_next(prev->thread, current->thread);
+
+ Py_XDECREF(prev);
+ prev = current;
+ }
+
+ if (current)
+ {
+ sr_thread_set_next(current->thread, NULL);
+ Py_XDECREF(current);
+ }
+
+ return 0;
+}
+
+int
+threads_free_python_list(struct sr_py_multi_stacktrace *stacktrace)
+{
+ int i;
+ PyObject *item;
+ for (i = 0; i < PyList_Size(stacktrace->threads); ++i)
+ {
+ item = PyList_GetItem(stacktrace->threads, i);
+ if (!item)
+ return -1;
+ Py_DECREF(item);
+ }
+ Py_DECREF(stacktrace->threads);
+
+ return 0;
+}
+
+PyObject *
+threads_to_python_list(struct sr_stacktrace *stacktrace, PyTypeObject *thread_type, PyTypeObject *frame_type)
+{
+ PyObject *result = PyList_New(0);
+ if (!result)
+ return PyErr_NoMemory();
+
+ struct sr_thread *thread = sr_stacktrace_threads(stacktrace);
+ struct sr_py_base_thread *item;
+ while (thread)
+ {
+ item = PyObject_New(struct sr_py_base_thread, thread_type);
+ if (!item)
+ return PyErr_NoMemory();
+
+ /* XXX may need to initialize further */
+ item->thread = thread;
+ item->frames = frames_to_python_list(thread, frame_type);
+ item->frame_type = frame_type;
+ if (!item->frames)
+ return NULL;
+
+ if (PyList_Append(result, (PyObject*)item) < 0)
+ return NULL;
+
+ thread = sr_thread_next(thread);
+ }
+
+ return result;
+}
+
+PyObject *
+sr_py_single_stacktrace_to_short_text(PyObject *self, PyObject *args)
+{
+ int max_frames = 0;
+ if (!PyArg_ParseTuple(args, "|i", &max_frames))
+ return NULL;
+
+ struct sr_py_base_thread *this = (struct sr_py_base_thread *)self;
+ if (frames_prepare_linked_list(this) < 0)
+ return NULL;
+
+ char *text =
+ sr_stacktrace_to_short_text((struct sr_stacktrace *)this->thread, max_frames);
+ if (!text)
+ return NULL;
+
+ PyObject *result = PyString_FromString(text);
+
+ free(text);
+ return result;
+}
+
+PyObject *
+sr_py_multi_stacktrace_to_short_text(PyObject *self, PyObject *args)
+{
+ int max_frames = 0;
+ if (!PyArg_ParseTuple(args, "|i", &max_frames))
+ return NULL;
+
+ struct sr_py_multi_stacktrace *this =
+ (struct sr_py_multi_stacktrace *)self;
+ if (threads_prepare_linked_list(this) < 0)
+ return NULL;
+
+ char *text =
+ sr_stacktrace_to_short_text((struct sr_stacktrace *)this->stacktrace, max_frames);
+ if (!text)
+ return NULL;
+
+ PyObject *result = PyString_FromString(text);
+
+ free(text);
+ return result;
+}
diff --git a/python/py_base_stacktrace.h b/python/py_base_stacktrace.h
new file mode 100644
index 0000000..a0d5e65
--- /dev/null
+++ b/python/py_base_stacktrace.h
@@ -0,0 +1,64 @@
+/*
+ py_base_stacktrace.h
+
+ Copyright (C) 2013 Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef SATYR_PY_BASE_STACKTRACE_H
+#define SATYR_PY_BASE_STACKTRACE_H
+
+/**
+ * @file
+ * @brief Base classes for stacktrace structures.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Python.h>
+#include <structmember.h>
+
+#include "py_base_thread.h"
+
+extern PyTypeObject sr_py_single_stacktrace_type;
+extern PyTypeObject sr_py_multi_stacktrace_type;
+
+/* Python object for multi threaded stacktraces. */
+struct sr_py_multi_stacktrace
+{
+ PyObject_HEAD
+ struct sr_stacktrace *stacktrace;
+ PyObject *threads;
+ PyTypeObject *thread_type;
+ PyTypeObject *frame_type;
+};
+
+/* helpers */
+int threads_prepare_linked_list(struct sr_py_multi_stacktrace *stacktrace);
+int threads_free_python_list(struct sr_py_multi_stacktrace *stacktrace);
+PyObject *threads_to_python_list(struct sr_stacktrace *stacktrace,
+ PyTypeObject *thread_type, PyTypeObject *frame_type);
+
+/* methods */
+PyObject *sr_py_single_stacktrace_to_short_text(PyObject *self, PyObject *args);
+PyObject *sr_py_multi_stacktrace_to_short_text(PyObject *self, PyObject *args);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/python/py_base_thread.c b/python/py_base_thread.c
new file mode 100644
index 0000000..6536c52
--- /dev/null
+++ b/python/py_base_thread.c
@@ -0,0 +1,205 @@
+/*
+ py_base_thread.c
+
+ Copyright (C) 2013 Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#include "py_common.h"
+#include "py_base_thread.h"
+#include "py_base_frame.h"
+
+#include "thread.h"
+#include "frame.h"
+
+#define thread_doc "satyr.BaseThread - base class for threads"
+#define frames_doc "A list containing objects representing frames in a thread."
+
+static PyMethodDef
+thread_methods[] =
+{
+ /* methods */
+ { NULL },
+};
+
+static PyMemberDef
+thread_members[] =
+{
+ { (char *)"frames", T_OBJECT_EX, offsetof(struct sr_py_base_thread, frames), 0, (char *)frames_doc },
+ { NULL },
+};
+
+PyTypeObject
+sr_py_base_thread_type =
+{
+ PyObject_HEAD_INIT(NULL)
+ 0,
+ "satyr.BaseThread", /* tp_name */
+ sizeof(struct sr_py_base_thread), /* tp_basicsize */
+ 0, /* tp_itemsize */
+ NULL, /* tp_dealloc */
+ NULL, /* tp_print */
+ NULL, /* tp_getattr */
+ NULL, /* tp_setattr */
+ (cmpfunc)sr_py_base_thread_cmp, /* tp_compare */
+ NULL, /* tp_repr */
+ NULL, /* tp_as_number */
+ NULL, /* tp_as_sequence */
+ NULL, /* tp_as_mapping */
+ NULL, /* tp_hash */
+ NULL, /* tp_call */
+ NULL, /* tp_str */
+ NULL, /* tp_getattro */
+ NULL, /* tp_setattro */
+ NULL, /* tp_as_buffer */
+ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE, /* tp_flags */
+ thread_doc, /* tp_doc */
+ NULL, /* tp_traverse */
+ NULL, /* tp_clear */
+ NULL, /* tp_richcompare */
+ 0, /* tp_weaklistoffset */
+ NULL, /* tp_iter */
+ NULL, /* tp_iternext */
+ thread_methods, /* tp_methods */
+ thread_members, /* tp_members */
+ NULL, /* tp_getset */
+ NULL, /* tp_base */
+ NULL, /* tp_dict */
+ NULL, /* tp_descr_get */
+ NULL, /* tp_descr_set */
+ 0, /* tp_dictoffset */
+ NULL, /* tp_init */
+ NULL, /* tp_alloc */
+ NULL, /* tp_new */
+ NULL, /* tp_free */
+ NULL, /* tp_is_gc */
+ NULL, /* tp_bases */
+ NULL, /* tp_mro */
+ NULL, /* tp_cache */
+ NULL, /* tp_subclasses */
+ NULL, /* tp_weaklist */
+};
+
+/* helpers */
+int
+frames_prepare_linked_list(struct sr_py_base_thread *thread)
+{
+ int i;
+ PyObject *item;
+ struct sr_py_base_frame *current = NULL, *prev = NULL;
+
+ for (i = 0; i < PyList_Size(thread->frames); ++i)
+ {
+ item = PyList_GetItem(thread->frames, i);
+ if (!item)
+ return -1;
+
+ Py_INCREF(item);
+
+ if (!PyObject_TypeCheck(item, thread->frame_type))
+ {
+ Py_XDECREF(item);
+ Py_XDECREF(prev);
+ PyErr_Format(PyExc_TypeError, "frames must be a list of %s objects",
+ thread->frame_type->tp_name);
+ return -1;
+ }
+
+ current = (struct sr_py_base_frame*)item;
+ if (i == 0)
+ sr_thread_set_frames(thread->thread, current->frame);
+ else
+ sr_frame_set_next(prev->frame, current->frame);
+
+ Py_XDECREF(prev);
+ prev = current;
+ }
+
+ if (current)
+ {
+ sr_frame_set_next(current->frame, NULL);
+ Py_DECREF(current);
+ }
+
+ return 0;
+}
+
+int
+frames_free_python_list(struct sr_py_base_thread *thread)
+{
+ int i;
+ PyObject *item;
+
+ for (i = 0; i < PyList_Size(thread->frames); ++i)
+ {
+ item = PyList_GetItem(thread->frames, i);
+ if (!item)
+ return -1;
+ Py_DECREF(item);
+ }
+ Py_DECREF(thread->frames);
+
+ return 0;
+}
+
+PyObject *
+frames_to_python_list(struct sr_thread *thread, PyTypeObject *frame_type)
+{
+ PyObject *result = PyList_New(0);
+ if (!result)
+ return NULL;
+
+ struct sr_frame *frame = sr_thread_frames(thread);
+ struct sr_py_base_frame *item;
+ while (frame)
+ {
+ item = PyObject_New(struct sr_py_base_frame, frame_type);
+ if (!item)
+ return PyErr_NoMemory();
+
+ /* XXX may need to initialize item further */
+ /* It would be a good idea to have a common code that is executed each
+ * time new object (e.g. via __new__ or _dup) is created so that we
+ * don't miss setting some attribute. As opposed to using PyObject_New
+ * directly. */
+ item->frame = frame;
+ if (PyList_Append(result, (PyObject *)item) < 0)
+ return NULL;
+
+ frame = sr_frame_next(frame);
+ }
+
+ return result;
+}
+
+/* comparison */
+int
+sr_py_base_thread_cmp(struct sr_py_base_thread *self, struct sr_py_base_thread *other)
+{
+ if (self->ob_type != other->ob_type)
+ {
+ /* distinct types must be unequal */
+ return normalize_cmp(self->ob_type - other->ob_type);
+ }
+
+ if (frames_prepare_linked_list(self) < 0
+ || frames_prepare_linked_list(other) < 0)
+ {
+ /* exception is already set */
+ return -1;
+ }
+
+ return normalize_cmp(sr_thread_cmp(self->thread, other->thread));
+}
diff --git a/python/py_base_thread.h b/python/py_base_thread.h
new file mode 100644
index 0000000..69ae0de
--- /dev/null
+++ b/python/py_base_thread.h
@@ -0,0 +1,56 @@
+/*
+ py_base_thread.h
+
+ Copyright (C) 2013 Red Hat, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+*/
+#ifndef SATYR_PY_BASE_THREAD_H
+#define SATYR_PY_BASE_THREAD_H
+
+/**
+ * @file
+ * @brief Base class for threads.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Python.h>
+#include <structmember.h>
+
+extern PyTypeObject sr_py_base_thread_type;
+
+struct sr_py_base_thread
+{
+ PyObject_HEAD
+ struct sr_thread *thread;
+ PyObject *frames;
+ PyTypeObject *frame_type;
+};
+
+/* helpers */
+int frames_prepare_linked_list(struct sr_py_base_thread *thread);
+int frames_free_python_list(struct sr_py_base_thread *thread);
+PyObject *frames_to_python_list(struct sr_thread *thread, PyTypeObject *frame_type);
+
+int sr_py_base_thread_cmp(struct sr_py_base_thread *self, struct sr_py_base_thread *other);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/python/py_gdb_stacktrace.c b/python/py_gdb_stacktrace.c
index d2f3a5d..8cd82fb 100644
--- a/python/py_gdb_stacktrace.c
+++ b/python/py_gdb_stacktrace.c
@@ -2,6 +2,8 @@
#include "py_gdb_thread.h"
#include "py_gdb_frame.h"
#include "py_gdb_sharedlib.h"
+#include "py_base_thread.h"
+#include "py_base_stacktrace.h"
#include "strbuf.h"
#include "gdb/stacktrace.h"
#include "gdb/thread.h"
@@ -96,7 +98,6 @@ gdb_stacktrace_methods[] =
static PyMemberDef
gdb_stacktrace_members[] =
{
- { (char *)"threads", T_OBJECT_EX, offsetof(struct sr_py_gdb_stacktrace, threads), 0, b_threads_doc },
{ (char *)"crashframe", T_OBJECT_EX, offsetof(struct sr_py_gdb_stacktrace, crashframe), READONLY, b_crashframe_doc },
{ (char *)"crashthread", T_OBJECT_EX, offsetof(struct sr_py_gdb_stacktrace, crashthread), READONLY, b_crashthread_doc },
{ (char *)"libs", T_OBJECT_EX, offsetof(struct sr_py_gdb_stacktrace, libs), 0, b_libs_doc },
@@ -135,7 +136,7 @@ PyTypeObject sr_py_gdb_stacktrace_type = {
gdb_stacktrace_methods, /* tp_methods */
gdb_stacktrace_members, /* tp_members */
NULL, /* tp_getset */
- NULL, /* tp_base */
+ &sr_py_multi_stacktrace_type, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
NULL, /* tp_descr_set */
@@ -153,50 +154,15 @@ PyTypeObject sr_py_gdb_stacktrace_type = {
};
/* helpers */
-int
-stacktrace_prepare_linked_list(struct sr_py_gdb_stacktrace *stacktrace)
+static int
+gdb_prepare_linked_lists(struct sr_py_gdb_stacktrace *stacktrace)
{
- int i;
- PyObject *item;
-
- /* thread */
- struct sr_py_gdb_thread *current = NULL, *prev = NULL;
- for (i = 0; i < PyList_Size(stacktrace->threads); ++i)
- {
- item = PyList_GetItem(stacktrace->threads, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
- if (!PyObject_TypeCheck(item, &sr_py_gdb_thread_type))
- {
- Py_XDECREF(current);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError,
- "threads must be a list of satyr.Thread objects");
- return -1;
- }
-
- current = (struct sr_py_gdb_thread*)item;
- if (thread_prepare_linked_list(current) < 0)
- return -1;
-
- if (i == 0)
- stacktrace->stacktrace->threads = current->thread;
- else
- prev->thread->next = current->thread;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->thread->next = NULL;
- Py_XDECREF(current);
- }
+ if (threads_prepare_linked_list((struct sr_py_multi_stacktrace *) stacktrace) < 0)
+ return -1;
/* sharedlib */
+ int i;
+ PyObject *item;
struct sr_py_gdb_sharedlib *currentlib = NULL, *prevlib = NULL;
for (i = 0; i < PyList_Size(stacktrace->libs); ++i)
{
@@ -282,8 +248,10 @@ thread_linked_list_to_python_list(struct sr_gdb_stacktrace *stacktrace)
item = (struct sr_py_gdb_thread*)
PyObject_New(struct sr_py_gdb_thread, &sr_py_gdb_thread_type);
+ item->frame_type = &sr_py_gdb_frame_type;
item->thread = thread;
- item->frames = frame_linked_list_to_python_list(thread);
+ item->frames = frames_to_python_list((struct sr_thread *)thread,
+ &sr_py_gdb_frame_type);
if (!item->frames)
return NULL;
@@ -320,6 +288,11 @@ sharedlib_linked_list_to_python_list(struct sr_gdb_stacktrace *stacktrace)
return result;
}
+/* XXX Why GDB stacktrace needs this function while other types do not? Is it
+ * because the methods here modify the linked lists and other types have no
+ * such methods? Shouldn't we do a copy of the linked list *before* we call the
+ * C function on it?
+ */
int
stacktrace_rebuild_thread_python_list(struct sr_py_gdb_stacktrace *stacktrace)
{
@@ -338,7 +311,8 @@ stacktrace_rebuild_thread_python_list(struct sr_py_gdb_stacktrace *stacktrace)
return -1;
}
stacktrace->stacktrace->threads = newlinkedlist;
- stacktrace->threads = thread_linked_list_to_python_list(stacktrace->stacktrace);
+ stacktrace->threads = threads_to_python_list((struct sr_stacktrace *)stacktrace->stacktrace,
+ &sr_py_gdb_thread_type, &sr_py_gdb_frame_type);
return 0;
}
@@ -381,6 +355,8 @@ sr_py_gdb_stacktrace_new(PyTypeObject *object,
if (!PyArg_ParseTuple(args, "|s", &str))
return NULL;
+ bo->thread_type = &sr_py_gdb_thread_type;
+ bo->frame_type = &sr_py_gdb_frame_type;
bo->crashframe = (struct sr_py_gdb_frame*)Py_None;
bo->crashthread = (struct sr_py_gdb_thread*)Py_None;
if (str)
@@ -443,7 +419,7 @@ PyObject *
sr_py_gdb_stacktrace_dup(PyObject *self, PyObject *args)
{
struct sr_py_gdb_stacktrace *this = (struct sr_py_gdb_stacktrace*)self;
- if (stacktrace_prepare_linked_list(this) < 0)
+ if (gdb_prepare_linked_lists(this) < 0)
return NULL;
struct sr_py_gdb_stacktrace *bo = (struct sr_py_gdb_stacktrace*)
@@ -453,6 +429,8 @@ sr_py_gdb_stacktrace_dup(PyObject *self, PyObject *args)
if (!bo)
return PyErr_NoMemory();
+ bo->thread_type = &sr_py_gdb_thread_type;
+ bo->frame_type = &sr_py_gdb_frame_type;
bo->stacktrace = sr_gdb_stacktrace_dup(this->stacktrace);
if (!bo->stacktrace)
return NULL;
@@ -490,7 +468,7 @@ PyObject *
sr_py_gdb_stacktrace_find_crash_frame(PyObject *self, PyObject *args)
{
struct sr_py_gdb_stacktrace *this = (struct sr_py_gdb_stacktrace *)self;
- if (stacktrace_prepare_linked_list(this) < 0)
+ if (gdb_prepare_linked_lists(this) < 0)
return NULL;
/* destroys linked list - need to rebuild python list */
@@ -520,7 +498,7 @@ PyObject *
sr_py_gdb_stacktrace_find_crash_thread(PyObject *self, PyObject *args)
{
struct sr_py_gdb_stacktrace *this = (struct sr_py_gdb_stacktrace*)self;
- if (stacktrace_prepare_linked_list(this) < 0)
+ if (gdb_prepare_linked_lists(this) < 0)
return NULL;
/* destroys linked list - need to rebuild python list */
@@ -537,8 +515,10 @@ sr_py_gdb_stacktrace_find_crash_thread(PyObject *self, PyObject *args)
if (!result)
return PyErr_NoMemory();
+ result->frame_type = &sr_py_gdb_frame_type;
result->thread = sr_gdb_thread_dup(thread, false);
- result->frames = frame_linked_list_to_python_list(result->thread);
+ result->frames = frames_to_python_list((struct sr_thread *)result->thread,
+ result->frame_type);
this->crashthread = result;
if (stacktrace_rebuild_thread_python_list(this) < 0)
@@ -551,7 +531,7 @@ PyObject *
sr_py_gdb_stacktrace_limit_frame_depth(PyObject *self, PyObject *args)
{
struct sr_py_gdb_stacktrace *this = (struct sr_py_gdb_stacktrace*)self;
- if (stacktrace_prepare_linked_list(this) < 0)
+ if (gdb_prepare_linked_lists(this) < 0)
return NULL;
int depth;
@@ -570,7 +550,7 @@ PyObject *
sr_py_gdb_stacktrace_quality_simple(PyObject *self, PyObject *args)
{
struct sr_py_gdb_stacktrace *this = (struct sr_py_gdb_stacktrace*)self;
- if (stacktrace_prepare_linked_list(this) < 0)
+ if (gdb_prepare_linked_lists(this) < 0)
return NULL;
/* does not destroy the linked list */
@@ -582,7 +562,7 @@ PyObject *
sr_py_gdb_stacktrace_quality_complex(PyObject *self, PyObject *args)
{
struct sr_py_gdb_stacktrace *this = (struct sr_py_gdb_stacktrace*)self;
- if (stacktrace_prepare_linked_list(this) < 0)
+ if (gdb_prepare_linked_lists(this) < 0)
return NULL;
/* does not destroy the linked list */
@@ -594,7 +574,7 @@ PyObject *
sr_py_gdb_stacktrace_get_duplication_hash(PyObject *self, PyObject *args)
{
struct sr_py_gdb_stacktrace *this = (struct sr_py_gdb_stacktrace*)self;
- if (stacktrace_prepare_linked_list(this) < 0)
+ if (gdb_prepare_linked_lists(this) < 0)
return NULL;
/* does not destroy the linked list */
@@ -609,7 +589,7 @@ PyObject *
sr_py_gdb_stacktrace_find_address(PyObject *self, PyObject *args)
{
struct sr_py_gdb_stacktrace *this = (struct sr_py_gdb_stacktrace*)self;
- if (stacktrace_prepare_linked_list(this) < 0)
+ if (gdb_prepare_linked_lists(this) < 0)
return NULL;
unsigned long long address;
@@ -642,7 +622,7 @@ PyObject *
sr_py_gdb_stacktrace_set_libnames(PyObject *self, PyObject *args)
{
struct sr_py_gdb_stacktrace *this = (struct sr_py_gdb_stacktrace*)self;
- if (stacktrace_prepare_linked_list(this) < 0)
+ if (gdb_prepare_linked_lists(this) < 0)
return NULL;
/* does not destroy the linked list */
@@ -657,7 +637,7 @@ PyObject *
sr_py_gdb_stacktrace_normalize(PyObject *self, PyObject *args)
{
struct sr_py_gdb_stacktrace *this = (struct sr_py_gdb_stacktrace*)self;
- if (stacktrace_prepare_linked_list(this) < 0)
+ if (gdb_prepare_linked_lists(this) < 0)
return NULL;
/* destroys the linked list and frees some parts */
@@ -685,7 +665,7 @@ PyObject *
sr_py_gdb_stacktrace_to_short_text(PyObject *self, PyObject *args)
{
struct sr_py_gdb_stacktrace *this = (struct sr_py_gdb_stacktrace*)self;
- if (stacktrace_prepare_linked_list(this) < 0)
+ if (gdb_prepare_linked_lists(this) < 0)
return NULL;
int max_frames = 0;
diff --git a/python/py_gdb_stacktrace.h b/python/py_gdb_stacktrace.h
index 1581958..fc2fc8b 100644
--- a/python/py_gdb_stacktrace.h
+++ b/python/py_gdb_stacktrace.h
@@ -37,20 +37,21 @@ struct sr_py_gdb_thread;
PyTypeObject sr_py_gdb_stacktrace_type;
+/* The beginning of this structure has to have the same layout as
+ * sr_py_multi_thread_stacktrace.
+ */
struct sr_py_gdb_stacktrace
{
PyObject_HEAD
struct sr_gdb_stacktrace *stacktrace;
PyObject *threads;
+ PyTypeObject *thread_type;
+ PyTypeObject *frame_type;
struct sr_py_gdb_frame *crashframe;
struct sr_py_gdb_thread *crashthread;
PyObject *libs;
};
-/* helpers */
-int stacktrace_prepare_linked_list(struct sr_py_gdb_stacktrace *stacktrace);
-PyObject *stacktrace_prepare_thread_list(struct sr_gdb_stacktrace *stacktrace);
-
/* constructor */
PyObject *sr_py_gdb_stacktrace_new(PyTypeObject *object,
PyObject *args,
diff --git a/python/py_gdb_thread.c b/python/py_gdb_thread.c
index 711d196..f9fde3c 100644
--- a/python/py_gdb_thread.c
+++ b/python/py_gdb_thread.c
@@ -1,4 +1,5 @@
#include "py_common.h"
+#include "py_base_thread.h"
#include "py_gdb_thread.h"
#include "py_gdb_frame.h"
#include "strbuf.h"
@@ -30,9 +31,6 @@
#define t_format_funs_doc "Usage: thread.format_funs()\n" \
"Returns: string"
-#define t_frames_doc (char *)"A list containing satyr.Frame objects representing " \
- "frames in a thread."
-
static PyMethodDef
gdb_thread_methods[] =
{
@@ -44,13 +42,6 @@ gdb_thread_methods[] =
{ NULL },
};
-static PyMemberDef
-gdb_thread_members[] =
-{
- { (char *)"frames", T_OBJECT_EX, offsetof(struct sr_py_gdb_thread, frames), 0, t_frames_doc },
- { NULL },
-};
-
/* See python/py_common.h and python/py_gdb_frame.c for generic getters/setters documentation. */
#define GSOFF_PY_STRUCT sr_py_gdb_thread
#define GSOFF_PY_MEMBER thread
@@ -77,7 +68,7 @@ PyTypeObject sr_py_gdb_thread_type =
NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
- (cmpfunc)sr_py_gdb_thread_cmp, /* tp_compare */
+ NULL, /* tp_compare */
NULL, /* tp_repr */
NULL, /* tp_as_number */
NULL, /* tp_as_sequence */
@@ -97,9 +88,9 @@ PyTypeObject sr_py_gdb_thread_type =
NULL, /* tp_iter */
NULL, /* tp_iternext */
gdb_thread_methods, /* tp_methods */
- gdb_thread_members, /* tp_members */
+ NULL, /* tp_members */
gdb_thread_getset, /* tp_getset */
- NULL, /* tp_base */
+ &sr_py_base_thread_type, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
NULL, /* tp_descr_set */
@@ -116,119 +107,6 @@ PyTypeObject sr_py_gdb_thread_type =
NULL, /* tp_weaklist */
};
-/* helpers */
-int
-thread_prepare_linked_list(struct sr_py_gdb_thread *thread)
-{
- int i;
- PyObject *item;
- struct sr_py_gdb_frame *current = NULL, *prev = NULL;
-
- for (i = 0; i < PyList_Size(thread->frames); ++i)
- {
- item = PyList_GetItem(thread->frames, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
-
- if (!PyObject_TypeCheck(item, &sr_py_gdb_frame_type))
- {
- Py_XDECREF(item);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError, "frames must be a list of satyr.Frame objects");
- return -1;
- }
-
- current = (struct sr_py_gdb_frame*)item;
- if (i == 0)
- thread->thread->frames = current->frame;
- else
- prev->frame->next = current->frame;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->frame->next = NULL;
- Py_DECREF(current);
- }
-
- return 0;
-}
-
-int
-thread_free_frame_python_list(struct sr_py_gdb_thread *thread)
-{
- int i;
- PyObject *item;
-
- for (i = 0; i < PyList_Size(thread->frames); ++i)
- {
- item = PyList_GetItem(thread->frames, i);
- if (!item)
- return -1;
- Py_DECREF(item);
- }
- Py_DECREF(thread->frames);
-
- return 0;
-}
-
-PyObject *
-frame_linked_list_to_python_list(struct sr_gdb_thread *thread)
-{
- PyObject *result = PyList_New(0);
- if (!result)
- return NULL;
-
- struct sr_gdb_frame *frame = thread->frames;
- struct sr_py_gdb_frame *item;
- while (frame)
- {
- item = (struct sr_py_gdb_frame*)
- PyObject_New(struct sr_py_gdb_frame, &sr_py_gdb_frame_type);
-
- if (!item)
- return PyErr_NoMemory();
-
- item->frame = frame;
- if (PyList_Append(result, (PyObject *)item) < 0)
- return NULL;
-
- frame = frame->next;
- }
-
- return result;
-}
-
-int
-thread_rebuild_python_list(struct sr_py_gdb_thread *thread)
-{
- struct sr_gdb_frame *newlinkedlist = sr_gdb_frame_dup(thread->thread->frames, true);
- if (thread_free_frame_python_list(thread) < 0)
- return -1;
- /* linked list */
- thread->thread->frames = newlinkedlist;
- /* python list */
- thread->frames = frame_linked_list_to_python_list(thread->thread);
- if (!thread->frames)
- {
- struct sr_gdb_frame *next;
- while (newlinkedlist)
- {
- next = newlinkedlist->next;
- sr_gdb_frame_free(newlinkedlist);
- newlinkedlist = next;
- }
- return -1;
- }
-
- return 0;
-}
-
/* constructor */
PyObject *
sr_py_gdb_thread_new(PyTypeObject *object, PyObject *args, PyObject *kwds)
@@ -240,6 +118,8 @@ sr_py_gdb_thread_new(PyTypeObject *object, PyObject *args, PyObject *kwds)
if (!to)
return PyErr_NoMemory();
+ to->frame_type = &sr_py_gdb_frame_type;
+
const char *str = NULL;
int only_funs = 0;
if (!PyArg_ParseTuple(args, "|si", &str, &only_funs))
@@ -262,7 +142,8 @@ sr_py_gdb_thread_new(PyTypeObject *object, PyObject *args, PyObject *kwds)
{
to->thread = sr_gdb_thread_parse_funs(str);
}
- to->frames = frame_linked_list_to_python_list(to->thread);
+ to->frames = frames_to_python_list((struct sr_thread*)to->thread,
+ to->frame_type);
if (!to->frames)
return NULL;
}
@@ -280,7 +161,7 @@ void
sr_py_gdb_thread_free(PyObject *object)
{
struct sr_py_gdb_thread *this = (struct sr_py_gdb_thread *)object;
- thread_free_frame_python_list(this);
+ frames_free_python_list((struct sr_py_base_thread*) this);
this->thread->frames = NULL;
sr_gdb_thread_free(this->thread);
PyObject_Del(object);
@@ -305,7 +186,7 @@ PyObject *
sr_py_gdb_thread_dup(PyObject *self, PyObject *args)
{
struct sr_py_gdb_thread *this = (struct sr_py_gdb_thread *)self;
- if (thread_prepare_linked_list(this) < 0)
+ if (frames_prepare_linked_list((struct sr_py_base_thread*) this) < 0)
return NULL;
struct sr_py_gdb_thread *to = (struct sr_py_gdb_thread*)
@@ -314,33 +195,23 @@ sr_py_gdb_thread_dup(PyObject *self, PyObject *args)
if (!to)
return PyErr_NoMemory();
+ to->frame_type = &sr_py_gdb_frame_type;
+
to->thread = sr_gdb_thread_dup(this->thread, false);
if (!to->thread)
return NULL;
- to->frames = frame_linked_list_to_python_list(to->thread);
+ to->frames = frames_to_python_list((struct sr_thread*)to->thread,
+ to->frame_type);
return (PyObject *)to;
}
-int
-sr_py_gdb_thread_cmp(struct sr_py_gdb_thread *self, struct sr_py_gdb_thread *other)
-{
- if (thread_prepare_linked_list(self) < 0
- || thread_prepare_linked_list(other) < 0)
- {
- /* exception is already set */
- return -1;
- }
-
- return normalize_cmp(sr_gdb_thread_cmp(self->thread, other->thread));
-}
-
PyObject *
sr_py_gdb_thread_quality_counts(PyObject *self, PyObject *args)
{
struct sr_py_gdb_thread *this = (struct sr_py_gdb_thread *)self;
- if (thread_prepare_linked_list(this) < 0)
+ if (frames_prepare_linked_list((struct sr_py_base_thread *)this) < 0)
return NULL;
int ok = 0, all = 0;
@@ -352,7 +223,7 @@ PyObject *
sr_py_gdb_thread_quality(PyObject *self, PyObject *args)
{
struct sr_py_gdb_thread *this = (struct sr_py_gdb_thread *)self;
- if (thread_prepare_linked_list(this) < 0)
+ if (frames_prepare_linked_list((struct sr_py_base_thread *)this) < 0)
return NULL;
return Py_BuildValue("f", sr_gdb_thread_quality(this->thread));
diff --git a/python/py_gdb_thread.h b/python/py_gdb_thread.h
index 00c32b9..39d5163 100644
--- a/python/py_gdb_thread.h
+++ b/python/py_gdb_thread.h
@@ -34,18 +34,17 @@ extern "C" {
PyTypeObject sr_py_gdb_thread_type;
+/* The beginning of this structure has to have the same layout as
+ * sr_py_base_thread.
+ */
struct sr_py_gdb_thread
{
PyObject_HEAD
- PyObject *frames;
struct sr_gdb_thread *thread;
+ PyObject *frames;
+ PyTypeObject *frame_type;
};
-/* helpers */
-int thread_prepare_linked_list(struct sr_py_gdb_thread *thread);
-PyObject *frame_linked_list_to_python_list(struct sr_gdb_thread *thread);
-int thread_rebuild_python_list(struct sr_py_gdb_thread *thread);
-
/* constructor */
PyObject *sr_py_gdb_thread_new(PyTypeObject *object,
PyObject *args,
@@ -57,9 +56,6 @@ void sr_py_gdb_thread_free(PyObject *object);
/* str */
PyObject *sr_py_gdb_thread_str(PyObject *self);
-/* cmp */
-int sr_py_gdb_thread_cmp(struct sr_py_gdb_thread *self, struct sr_py_gdb_thread *other);
-
/* methods */
PyObject *sr_py_gdb_thread_dup(PyObject *self, PyObject *args);
PyObject *sr_py_gdb_thread_quality_counts(PyObject *self, PyObject *args);
diff --git a/python/py_java_stacktrace.c b/python/py_java_stacktrace.c
index 71167e2..7a9477d 100644
--- a/python/py_java_stacktrace.c
+++ b/python/py_java_stacktrace.c
@@ -1,3 +1,4 @@
+#include "py_base_stacktrace.h"
#include "py_java_stacktrace.h"
#include "py_java_thread.h"
#include "py_java_frame.h"
@@ -25,25 +26,15 @@
#define b_normalize_doc "Usage: stacktrace.normalize()\n" \
"Normalizes all threads in the stacktrace."
-#define b_threads_doc (char *)"A list containing the satyr.JavaThread objects " \
- "representing threads in the stacktrace."
-
static PyMethodDef
java_stacktrace_methods[] =
{
/* methods */
{ "dup", sr_py_java_stacktrace_dup, METH_NOARGS, b_dup_doc },
- { "to_short_text", sr_py_java_stacktrace_to_short_text, METH_VARARGS, b_to_short_text },
// { "normalize", sr_py_java_stacktrace_normalize, METH_NOARGS, b_normalize_doc },
{ NULL },
};
-static PyMemberDef
-java_stacktrace_members[] =
-{
- { (char *)"threads", T_OBJECT_EX, offsetof(struct sr_py_java_stacktrace, threads), 0, b_threads_doc },
- { NULL },
-};
PyTypeObject sr_py_java_stacktrace_type = {
PyObject_HEAD_INIT(NULL)
@@ -75,9 +66,9 @@ PyTypeObject sr_py_java_stacktrace_type = {
NULL, /* tp_iter */
NULL, /* tp_iternext */
java_stacktrace_methods, /* tp_methods */
- java_stacktrace_members, /* tp_members */
+ NULL, /* tp_members */
NULL, /* tp_getset */
- NULL, /* tp_base */
+ &sr_py_multi_stacktrace_type, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
NULL, /* tp_descr_set */
@@ -94,98 +85,6 @@ PyTypeObject sr_py_java_stacktrace_type = {
NULL, /* tp_weaklist */
};
-/* helpers */
-int
-java_stacktrace_prepare_linked_list(struct sr_py_java_stacktrace *stacktrace)
-{
- int i;
- PyObject *item;
-
- /* thread */
- struct sr_py_java_thread *current = NULL, *prev = NULL;
- for (i = 0; i < PyList_Size(stacktrace->threads); ++i)
- {
- item = PyList_GetItem(stacktrace->threads, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
- if (!PyObject_TypeCheck(item, &sr_py_java_thread_type))
- {
- Py_XDECREF(current);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError,
- "threads must be a list of satyr.JavaThread objects");
- return -1;
- }
-
- current = (struct sr_py_java_thread*)item;
- if (java_thread_prepare_linked_list(current) < 0)
- return -1;
-
- if (i == 0)
- stacktrace->stacktrace->threads = current->thread;
- else
- prev->thread->next = current->thread;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->thread->next = NULL;
- Py_XDECREF(current);
- }
-
- return 0;
-}
-
-int
-java_stacktrace_free_thread_python_list(struct sr_py_java_stacktrace *stacktrace)
-{
- int i;
- PyObject *item;
- for (i = 0; i < PyList_Size(stacktrace->threads); ++i)
- {
- item = PyList_GetItem(stacktrace->threads, i);
- if (!item)
- return -1;
- Py_DECREF(item);
- }
- Py_DECREF(stacktrace->threads);
-
- return 0;
-}
-
-PyObject *
-java_thread_linked_list_to_python_list(struct sr_java_stacktrace *stacktrace)
-{
- PyObject *result = PyList_New(0);
- if (!result)
- return PyErr_NoMemory();
-
- struct sr_java_thread *thread = stacktrace->threads;
- struct sr_py_java_thread *item;
- while (thread)
- {
- item = (struct sr_py_java_thread*)
- PyObject_New(struct sr_py_java_thread, &sr_py_java_thread_type);
-
- item->thread = thread;
- item->frames = java_frame_linked_list_to_python_list(thread);
- if (!item->frames)
- return NULL;
-
- if (PyList_Append(result, (PyObject*)item) < 0)
- return NULL;
-
- thread = thread->next;
- }
-
- return result;
-}
-
/* constructor */
PyObject *
sr_py_java_stacktrace_new(PyTypeObject *object,
@@ -199,6 +98,9 @@ sr_py_java_stacktrace_new(PyTypeObject *object,
if (!bo)
return PyErr_NoMemory();
+ bo->thread_type = &sr_py_java_thread_type;
+ bo->frame_type = &sr_py_java_frame_type;
+
const char *str = NULL;
if (!PyArg_ParseTuple(args, "|s", &str))
return NULL;
@@ -214,7 +116,8 @@ sr_py_java_stacktrace_new(PyTypeObject *object,
PyErr_SetString(PyExc_ValueError, location.message);
return NULL;
}
- bo->threads = java_thread_linked_list_to_python_list(bo->stacktrace);
+ bo->threads = threads_to_python_list((struct sr_stacktrace *)bo->stacktrace,
+ bo->thread_type, bo->frame_type);
if (!bo->threads)
return NULL;
}
@@ -232,7 +135,7 @@ void
sr_py_java_stacktrace_free(PyObject *object)
{
struct sr_py_java_stacktrace *this = (struct sr_py_java_stacktrace*)object;
- java_stacktrace_free_thread_python_list(this);
+ threads_free_python_list((struct sr_py_multi_stacktrace *)this);
this->stacktrace->threads = NULL;
sr_java_stacktrace_free(this->stacktrace);
PyObject_Del(object);
@@ -257,7 +160,7 @@ PyObject *
sr_py_java_stacktrace_dup(PyObject *self, PyObject *args)
{
struct sr_py_java_stacktrace *this = (struct sr_py_java_stacktrace*)self;
- if (java_stacktrace_prepare_linked_list(this) < 0)
+ if (threads_prepare_linked_list((struct sr_py_multi_stacktrace *)this) < 0)
return NULL;
struct sr_py_java_stacktrace *bo = (struct sr_py_java_stacktrace*)
@@ -267,39 +170,21 @@ sr_py_java_stacktrace_dup(PyObject *self, PyObject *args)
if (!bo)
return PyErr_NoMemory();
+ bo->thread_type = &sr_py_java_thread_type;
+ bo->frame_type = &sr_py_java_frame_type;
+
bo->stacktrace = sr_java_stacktrace_dup(this->stacktrace);
if (!bo->stacktrace)
return NULL;
- bo->threads = java_thread_linked_list_to_python_list(bo->stacktrace);
+ bo->threads = threads_to_python_list((struct sr_stacktrace *)bo->stacktrace,
+ bo->thread_type, bo->frame_type);
if (!bo->threads)
return NULL;
return (PyObject*)bo;
}
-PyObject *
-sr_py_java_stacktrace_to_short_text(PyObject *self, PyObject *args)
-{
- int max_frames = 0;
- if (!PyArg_ParseTuple(args, "|i", &max_frames))
- return NULL;
-
- struct sr_py_java_stacktrace *this = (struct sr_py_java_stacktrace*)self;
- if (java_stacktrace_prepare_linked_list(this) < 0)
- return NULL;
-
- char *text =
- sr_stacktrace_to_short_text((struct sr_stacktrace *)this->stacktrace, max_frames);
- if (!text)
- return NULL;
-
- PyObject *result = PyString_FromString(text);
-
- free(text);
- return result;
-}
-
/*
* Normalization not yet implemente for java stacktraces
*
@@ -307,7 +192,7 @@ PyObject *
sr_py_java_stacktrace_normalize(PyObject *self, PyObject *args)
{
struct sr_py_java_stacktrace *this = (struct sr_py_java_stacktrace*)self;
- if (java_stacktrace_prepare_linked_list(this) < 0)
+ if (threads_prepare_linked_list((struct sr_py_multi_stacktrace *)this) < 0)
return NULL;
struct sr_java_stacktrace *tmp = sr_java_stacktrace_dup(this->stacktrace);
diff --git a/python/py_java_stacktrace.h b/python/py_java_stacktrace.h
index 74996dc..4802d57 100644
--- a/python/py_java_stacktrace.h
+++ b/python/py_java_stacktrace.h
@@ -37,17 +37,18 @@ struct sr_py_java_thread;
PyTypeObject sr_py_java_stacktrace_type;
+/* The beginning of this structure has to have the same layout as
+ * sr_py_multi_thread_stacktrace.
+ */
struct sr_py_java_stacktrace
{
PyObject_HEAD
struct sr_java_stacktrace *stacktrace;
PyObject *threads;
+ PyTypeObject *thread_type;
+ PyTypeObject *frame_type;
};
-/* helpers */
-int java_stacktrace_prepare_linked_list(struct sr_py_java_stacktrace *stacktrace);
-PyObject *java_stacktrace_prepare_thread_list(struct sr_java_stacktrace *stacktrace);
-
/* constructor */
PyObject *sr_py_java_stacktrace_new(PyTypeObject *object,
PyObject *args,
@@ -62,7 +63,6 @@ PyObject *sr_py_java_stacktrace_str(PyObject *self);
/* methods */
PyObject *sr_py_java_stacktrace_dup(PyObject *self, PyObject *args);
PyObject *sr_py_java_stacktrace_normalize(PyObject *self, PyObject *args);
-PyObject *sr_py_java_stacktrace_to_short_text(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
diff --git a/python/py_java_thread.c b/python/py_java_thread.c
index c960e37..3c8a77b 100644
--- a/python/py_java_thread.c
+++ b/python/py_java_thread.c
@@ -1,4 +1,5 @@
#include "py_common.h"
+#include "py_base_thread.h"
#include "py_java_thread.h"
#include "py_java_frame.h"
#include "strbuf.h"
@@ -45,13 +46,6 @@ java_thread_methods[] =
{ NULL },
};
-static PyMemberDef
-java_thread_members[] =
-{
- { (char *)"frames", T_OBJECT_EX, offsetof(struct sr_py_java_thread, frames), 0, t_frames_doc },
- { NULL },
-};
-
/* See python/py_common.h and python/py_gdb_frame.c for generic getters/setters documentation. */
#define GSOFF_PY_STRUCT sr_py_java_thread
#define GSOFF_PY_MEMBER thread
@@ -78,7 +72,7 @@ PyTypeObject sr_py_java_thread_type =
NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
- (cmpfunc)sr_py_java_thread_cmp, /* tp_compare */
+ NULL, /* tp_compare */
NULL, /* tp_repr */
NULL, /* tp_as_number */
NULL, /* tp_as_sequence */
@@ -98,9 +92,9 @@ PyTypeObject sr_py_java_thread_type =
NULL, /* tp_iter */
NULL, /* tp_iternext */
java_thread_methods, /* tp_methods */
- java_thread_members, /* tp_members */
+ NULL, /* tp_members */
java_thread_getset, /* tp_getset */
- NULL, /* tp_base */
+ &sr_py_base_thread_type, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
NULL, /* tp_descr_set */
@@ -117,94 +111,6 @@ PyTypeObject sr_py_java_thread_type =
NULL, /* tp_weaklist */
};
-/* helpers */
-int
-java_thread_prepare_linked_list(struct sr_py_java_thread *thread)
-{
- int i;
- PyObject *item;
- struct sr_py_java_frame *current = NULL, *prev = NULL;
-
- for (i = 0; i < PyList_Size(thread->frames); ++i)
- {
- item = PyList_GetItem(thread->frames, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
-
- if (!PyObject_TypeCheck(item, &sr_py_java_frame_type))
- {
- Py_XDECREF(item);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError, "frames must be a list of satyr.JavaFrame objects");
- return -1;
- }
-
- current = (struct sr_py_java_frame*)item;
- if (i == 0)
- thread->thread->frames = current->frame;
- else
- prev->frame->next = current->frame;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->frame->next = NULL;
- Py_DECREF(current);
- }
-
- return 0;
-}
-
-int
-java_thread_free_frame_python_list(struct sr_py_java_thread *thread)
-{
- int i;
- PyObject *item;
-
- for (i = 0; i < PyList_Size(thread->frames); ++i)
- {
- item = PyList_GetItem(thread->frames, i);
- if (!item)
- return -1;
- Py_DECREF(item);
- }
- Py_DECREF(thread->frames);
-
- return 0;
-}
-
-PyObject *
-java_frame_linked_list_to_python_list(struct sr_java_thread *thread)
-{
- PyObject *result = PyList_New(0);
- if (!result)
- return NULL;
-
- struct sr_java_frame *frame = thread->frames;
- struct sr_py_java_frame *item;
- while (frame)
- {
- item = (struct sr_py_java_frame*)
- PyObject_New(struct sr_py_java_frame, &sr_py_java_frame_type);
-
- if (!item)
- return PyErr_NoMemory();
-
- item->frame = frame;
- if (PyList_Append(result, (PyObject *)item) < 0)
- return NULL;
-
- frame = frame->next;
- }
-
- return result;
-}
-
/* constructor */
PyObject *
sr_py_java_thread_new(PyTypeObject *object, PyObject *args, PyObject *kwds)
@@ -216,6 +122,8 @@ sr_py_java_thread_new(PyTypeObject *object, PyObject *args, PyObject *kwds)
if (!to)
return PyErr_NoMemory();
+ to->frame_type = &sr_py_java_frame_type;
+
const char *str = NULL;
if (!PyArg_ParseTuple(args, "|s", &str))
return NULL;
@@ -230,7 +138,7 @@ sr_py_java_thread_new(PyTypeObject *object, PyObject *args, PyObject *kwds)
PyErr_SetString(PyExc_ValueError, location.message);
return NULL;
}
- to->frames = java_frame_linked_list_to_python_list(to->thread);
+ to->frames = frames_to_python_list((struct sr_thread *)to->thread, to->frame_type);
if (!to->frames)
return NULL;
}
@@ -248,7 +156,7 @@ void
sr_py_java_thread_free(PyObject *object)
{
struct sr_py_java_thread *this = (struct sr_py_java_thread *)object;
- java_thread_free_frame_python_list(this);
+ frames_free_python_list((struct sr_py_base_thread *)this);
this->thread->frames = NULL;
sr_java_thread_free(this->thread);
PyObject_Del(object);
@@ -275,7 +183,7 @@ PyObject *
sr_py_java_thread_dup(PyObject *self, PyObject *args)
{
struct sr_py_java_thread *this = (struct sr_py_java_thread *)self;
- if (java_thread_prepare_linked_list(this) < 0)
+ if (frames_prepare_linked_list((struct sr_py_base_thread *)this) < 0)
return NULL;
struct sr_py_java_thread *to = (struct sr_py_java_thread*)
@@ -284,33 +192,21 @@ sr_py_java_thread_dup(PyObject *self, PyObject *args)
if (!to)
return PyErr_NoMemory();
+ to->frame_type = &sr_py_java_frame_type;
to->thread = sr_java_thread_dup(this->thread, false);
if (!to->thread)
return NULL;
- to->frames = java_frame_linked_list_to_python_list(to->thread);
+ to->frames = frames_to_python_list((struct sr_thread *)to->thread, to->frame_type);
return (PyObject *)to;
}
-int
-sr_py_java_thread_cmp(struct sr_py_java_thread *self, struct sr_py_java_thread *other)
-{
- if (java_thread_prepare_linked_list(self) < 0
- || java_thread_prepare_linked_list(other) < 0)
- {
- /* exception is already set */
- return -1;
- }
-
- return normalize_cmp(sr_java_thread_cmp(self->thread, other->thread));
-}
-
PyObject *
sr_py_java_thread_quality_counts(PyObject *self, PyObject *args)
{
struct sr_py_java_thread *this = (struct sr_py_java_thread *)self;
- if (java_thread_prepare_linked_list(this) < 0)
+ if (frames_prepare_linked_list((struct sr_py_base_thread *)this) < 0)
return NULL;
int ok = 0, all = 0;
@@ -322,7 +218,7 @@ PyObject *
sr_py_java_thread_quality(PyObject *self, PyObject *args)
{
struct sr_py_java_thread *this = (struct sr_py_java_thread *)self;
- if (java_thread_prepare_linked_list(this) < 0)
+ if (frames_prepare_linked_list((struct sr_py_base_thread *)this) < 0)
return NULL;
return Py_BuildValue("f", sr_java_thread_quality(this->thread));
diff --git a/python/py_java_thread.h b/python/py_java_thread.h
index f9958f6..0abe8bc 100644
--- a/python/py_java_thread.h
+++ b/python/py_java_thread.h
@@ -34,18 +34,17 @@ extern "C" {
PyTypeObject sr_py_java_thread_type;
+/* The beginning of this structure has to have the same layout as
+ * sr_py_base_thread.
+ */
struct sr_py_java_thread
{
PyObject_HEAD
- PyObject *frames;
struct sr_java_thread *thread;
+ PyObject *frames;
+ PyTypeObject *frame_type;
};
-/* helpers */
-int java_thread_prepare_linked_list(struct sr_py_java_thread *thread);
-PyObject *java_frame_linked_list_to_python_list(struct sr_java_thread *thread);
-int java_thread_rebuild_python_list(struct sr_py_java_thread *thread);
-
/* constructor */
PyObject *sr_py_java_thread_new(PyTypeObject *object,
PyObject *args,
@@ -57,9 +56,6 @@ void sr_py_java_thread_free(PyObject *object);
/* str */
PyObject *sr_py_java_thread_str(PyObject *self);
-/* cmp */
-int sr_py_java_thread_cmp(struct sr_py_java_thread *self, struct sr_py_java_thread *other);
-
/* methods */
PyObject *sr_py_java_thread_dup(PyObject *self, PyObject *args);
PyObject *sr_py_java_thread_quality_counts(PyObject *self, PyObject *args);
diff --git a/python/py_koops_stacktrace.c b/python/py_koops_stacktrace.c
index 5a14066..97a38ef 100644
--- a/python/py_koops_stacktrace.c
+++ b/python/py_koops_stacktrace.c
@@ -1,5 +1,6 @@
#include "py_koops_frame.h"
#include "py_koops_stacktrace.h"
+#include "py_base_stacktrace.h"
#include "py_common.h"
#include "strbuf.h"
#include "koops/frame.h"
@@ -37,14 +38,6 @@ koops_stacktrace_methods[] =
/* methods */
{ "dup", sr_py_koops_stacktrace_dup, METH_NOARGS, b_dup_doc },
{ "normalize", sr_py_koops_stacktrace_normalize, METH_NOARGS, b_normalize_doc },
- { "to_short_text", sr_py_koops_stacktrace_to_short_text, METH_VARARGS, b_to_short_text },
- { NULL },
-};
-
-static PyMemberDef
-koops_stacktrace_members[] =
-{
- { (char *)"frames", T_OBJECT_EX, offsetof(struct sr_py_koops_stacktrace, frames), 0, (char *) b_frames_doc },
{ NULL },
};
@@ -86,9 +79,9 @@ PyTypeObject sr_py_koops_stacktrace_type = {
NULL, /* tp_iter */
NULL, /* tp_iternext */
koops_stacktrace_methods, /* tp_methods */
- koops_stacktrace_members, /* tp_members */
+ NULL, /* tp_members */
koops_stacktrace_getset, /* tp_getset */
- NULL, /* tp_base */
+ &sr_py_single_stacktrace_type, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
NULL, /* tp_descr_set */
@@ -105,49 +98,6 @@ PyTypeObject sr_py_koops_stacktrace_type = {
NULL, /* tp_weaklist */
};
-/* helpers */
-int
-koops_stacktrace_prepare_linked_list(struct sr_py_koops_stacktrace *stacktrace)
-{
- int i;
- PyObject *item;
-
- struct sr_py_koops_frame *current = NULL, *prev = NULL;
- for (i = 0; i < PyList_Size(stacktrace->frames); ++i)
- {
- item = PyList_GetItem(stacktrace->frames, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
- if (!PyObject_TypeCheck(item, &sr_py_koops_frame_type))
- {
- Py_XDECREF(current);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError,
- "frames must be a list of satyr.KerneloopsFrame objects");
- return -1;
- }
-
- current = (struct sr_py_koops_frame*)item;
- if (i == 0)
- stacktrace->stacktrace->frames = current->frame;
- else
- prev->frame->next = current->frame;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->frame->next = NULL;
- Py_XDECREF(current);
- }
-
- return 0;
-}
-
PyObject *
sr_py_koops_stacktrace_get_modules(PyObject *self, void *data)
{
@@ -197,52 +147,6 @@ sr_py_koops_stacktrace_set_taint_flags(PyObject *self, PyObject *rhs, void *data
return -1;
}
-PyObject *
-koops_frame_linked_list_to_python_list(struct sr_koops_stacktrace *stacktrace)
-{
- PyObject *result = PyList_New(0);
- if (!result)
- return PyErr_NoMemory();
-
- struct sr_koops_frame *frame = stacktrace->frames;
- struct sr_py_koops_frame *item;
-
- while(frame)
- {
- item = (struct sr_py_koops_frame*)
- PyObject_New(struct sr_py_koops_frame, &sr_py_koops_frame_type);
-
- if (!item)
- return PyErr_NoMemory();
-
- item->frame = frame;
- if (PyList_Append(result, (PyObject *)item) < 0)
- return NULL;
-
- frame = frame->next;
- }
-
- return result;
-}
-
-int
-koops_free_frame_python_list(struct sr_py_koops_stacktrace *stacktrace)
-{
- int i;
- PyObject *item;
-
- for (i = 0; i < PyList_Size(stacktrace->frames); ++i)
- {
- item = PyList_GetItem(stacktrace->frames, i);
- if (!item)
- return -1;
- Py_DECREF(item);
- }
- Py_DECREF(stacktrace->frames);
-
- return 0;
-}
-
/* constructor */
PyObject *
sr_py_koops_stacktrace_new(PyTypeObject *object,
@@ -256,6 +160,8 @@ sr_py_koops_stacktrace_new(PyTypeObject *object,
if (!bo)
return PyErr_NoMemory();
+ bo->frame_type = &sr_py_koops_frame_type;
+
const char *str = NULL;
if (!PyArg_ParseTuple(args, "|s", &str))
return NULL;
@@ -271,7 +177,7 @@ sr_py_koops_stacktrace_new(PyTypeObject *object,
return NULL;
}
- bo->frames = koops_frame_linked_list_to_python_list(bo->stacktrace);
+ bo->frames = frames_to_python_list((struct sr_thread *)bo->stacktrace, bo->frame_type);
}
else
{
@@ -287,7 +193,7 @@ void
sr_py_koops_stacktrace_free(PyObject *object)
{
struct sr_py_koops_stacktrace *this = (struct sr_py_koops_stacktrace*)object;
- koops_free_frame_python_list(this);
+ frames_free_python_list((struct sr_py_base_thread *)this);
this->stacktrace->frames = NULL;
sr_koops_stacktrace_free(this->stacktrace);
PyObject_Del(object);
@@ -312,7 +218,7 @@ PyObject *
sr_py_koops_stacktrace_dup(PyObject *self, PyObject *args)
{
struct sr_py_koops_stacktrace *this = (struct sr_py_koops_stacktrace*)self;
- if (koops_stacktrace_prepare_linked_list(this) < 0)
+ if (frames_prepare_linked_list((struct sr_py_base_thread *)this) < 0)
return NULL;
struct sr_py_koops_stacktrace *bo = (struct sr_py_koops_stacktrace*)
@@ -322,11 +228,12 @@ sr_py_koops_stacktrace_dup(PyObject *self, PyObject *args)
if (!bo)
return PyErr_NoMemory();
+ bo->frame_type = &sr_py_koops_frame_type;
bo->stacktrace = sr_koops_stacktrace_dup(this->stacktrace);
if (!bo->stacktrace)
return NULL;
- bo->frames = koops_frame_linked_list_to_python_list(bo->stacktrace);
+ bo->frames = frames_to_python_list((struct sr_thread *)bo->stacktrace, bo->frame_type);
if (!bo->frames)
return NULL;
@@ -337,14 +244,14 @@ PyObject *
sr_py_koops_stacktrace_normalize(PyObject *self, PyObject *args)
{
struct sr_py_koops_stacktrace *this = (struct sr_py_koops_stacktrace*)self;
- if (koops_stacktrace_prepare_linked_list(this) < 0)
+ if (frames_prepare_linked_list((struct sr_py_base_thread *)this) < 0)
return NULL;
/* destroys the linked list and frees some parts */
/* need to rebuild python list manually */
struct sr_koops_stacktrace *tmp = sr_koops_stacktrace_dup(this->stacktrace);
sr_normalize_koops_stacktrace(tmp);
- if (koops_free_frame_python_list(this) < 0)
+ if (frames_free_python_list((struct sr_py_base_thread *)this) < 0)
{
sr_koops_stacktrace_free(tmp);
return NULL;
@@ -354,31 +261,9 @@ sr_py_koops_stacktrace_normalize(PyObject *self, PyObject *args)
tmp->frames = NULL;
sr_koops_stacktrace_free(tmp);
- this->frames = koops_frame_linked_list_to_python_list(this->stacktrace);
+ this->frames = frames_to_python_list((struct sr_thread *)this->stacktrace, this->frame_type);
if (!this->frames)
return NULL;
Py_RETURN_NONE;
}
-
-PyObject *
-sr_py_koops_stacktrace_to_short_text(PyObject *self, PyObject *args)
-{
- int max_frames = 0;
- if (!PyArg_ParseTuple(args, "|i", &max_frames))
- return NULL;
-
- struct sr_py_koops_stacktrace *this = (struct sr_py_koops_stacktrace*)self;
- if (koops_stacktrace_prepare_linked_list(this) < 0)
- return NULL;
-
- char *text =
- sr_stacktrace_to_short_text((struct sr_stacktrace *)this->stacktrace, max_frames);
- if (!text)
- return NULL;
-
- PyObject *result = PyString_FromString(text);
-
- free(text);
- return result;
-}
diff --git a/python/py_koops_stacktrace.h b/python/py_koops_stacktrace.h
index 100be66..162ac5e 100644
--- a/python/py_koops_stacktrace.h
+++ b/python/py_koops_stacktrace.h
@@ -34,12 +34,16 @@ extern "C" {
PyTypeObject sr_py_koops_stacktrace_type;
+/* The beginning of this structure has to have the same layout as
+ * sr_py_base_thread.
+ */
struct sr_py_koops_stacktrace
{
PyObject_HEAD
+ struct sr_koops_stacktrace *stacktrace;
PyObject *frames;
+ PyTypeObject *frame_type;
PyObject *taint_flags;
- struct sr_koops_stacktrace *stacktrace;
};
/* constructor */
@@ -62,7 +66,6 @@ int sr_py_koops_stacktrace_set_taint_flags(PyObject *self, PyObject *rhs, void *
/* methods */
PyObject *sr_py_koops_stacktrace_dup(PyObject *self, PyObject *args);
PyObject *sr_py_koops_stacktrace_normalize(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_stacktrace_to_short_text(PyObject *self, PyObject *args);
#ifdef __cplusplus
diff --git a/python/py_module.c b/python/py_module.c
index 6759091..5e1f60a 100644
--- a/python/py_module.c
+++ b/python/py_module.c
@@ -1,6 +1,8 @@
#include <Python.h>
#include "py_cluster.h"
#include "py_base_frame.h"
+#include "py_base_thread.h"
+#include "py_base_stacktrace.h"
#include "py_gdb_frame.h"
#include "py_gdb_sharedlib.h"
#include "py_gdb_stacktrace.h"
@@ -35,6 +37,24 @@ init_satyr()
return;
}
+ if (PyType_Ready(&sr_py_base_thread_type) < 0)
+ {
+ puts("PyType_Ready(&sr_py_base_thread_type) < 0");
+ return;
+ }
+
+ if (PyType_Ready(&sr_py_single_stacktrace_type) < 0)
+ {
+ puts("PyType_Ready(&sr_py_single_stacktrace_type) < 0");
+ return;
+ }
+
+ if (PyType_Ready(&sr_py_multi_stacktrace_type) < 0)
+ {
+ puts("PyType_Ready(&sr_py_multi_stacktrace_type) < 0");
+ return;
+ }
+
if (PyType_Ready(&sr_py_gdb_frame_type) < 0)
{
puts("PyType_Ready(&sr_py_gdb_frame_type) < 0");
diff --git a/python/py_python_stacktrace.c b/python/py_python_stacktrace.c
index e35b0fa..0f16b07 100644
--- a/python/py_python_stacktrace.c
+++ b/python/py_python_stacktrace.c
@@ -1,6 +1,7 @@
#include "py_common.h"
#include "py_python_frame.h"
#include "py_python_stacktrace.h"
+#include "py_base_stacktrace.h"
#include "utils.h"
#include "strbuf.h"
#include "python/frame.h"
@@ -36,18 +37,10 @@ python_stacktrace_methods[] =
{
/* methods */
{ "dup", sr_py_python_stacktrace_dup, METH_NOARGS, f_dup_doc },
- { "to_short_text", sr_py_python_stacktrace_to_short_text, METH_VARARGS, f_to_short_text },
// { "normalize", sr_py_python_stacktrace_normalize, METH_NOARGS, f_normalize_doc },
{ NULL },
};
-static PyMemberDef
-python_stacktrace_members[] =
-{
- { (char *)"frames", T_OBJECT_EX, offsetof(struct sr_py_python_stacktrace, frames), 0, (char *)f_frames_doc },
- { NULL },
-};
-
/* See python/py_common.h and python/py_gdb_frame.c for generic getters/setters documentation. */
#define GSOFF_PY_STRUCT sr_py_python_stacktrace
#define GSOFF_PY_MEMBER stacktrace
@@ -93,9 +86,9 @@ PyTypeObject sr_py_python_stacktrace_type = {
NULL, /* tp_iter */
NULL, /* tp_iternext */
python_stacktrace_methods, /* tp_methods */
- python_stacktrace_members, /* tp_members */
+ NULL, /* tp_members */
python_stacktrace_getset, /* tp_getset */
- NULL, /* tp_base */
+ &sr_py_single_stacktrace_type, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
NULL, /* tp_descr_set */
@@ -112,95 +105,6 @@ PyTypeObject sr_py_python_stacktrace_type = {
NULL, /* tp_weaklist */
};
-/* helpers */
-int
-python_stacktrace_prepare_linked_list(struct sr_py_python_stacktrace *stacktrace)
-{
- int i;
- PyObject *item;
-
- struct sr_py_python_frame *current = NULL, *prev = NULL;
- for (i = 0; i < PyList_Size(stacktrace->frames); ++i)
- {
- item = PyList_GetItem(stacktrace->frames, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
- if (!PyObject_TypeCheck(item, &sr_py_python_frame_type))
- {
- Py_XDECREF(current);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError,
- "frames must be a list of satyr.PythonFrame objects");
- return -1;
- }
-
- current = (struct sr_py_python_frame*)item;
- if (i == 0)
- stacktrace->stacktrace->frames = current->frame;
- else
- prev->frame->next = current->frame;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->frame->next = NULL;
- Py_XDECREF(current);
- }
-
- return 0;
-}
-
-PyObject *
-python_frame_linked_list_to_python_list(struct sr_python_stacktrace *stacktrace)
-{
- PyObject *result = PyList_New(0);
- if (!result)
- return PyErr_NoMemory();
-
- struct sr_python_frame *frame = stacktrace->frames;
- struct sr_py_python_frame *item;
-
- while(frame)
- {
- item = (struct sr_py_python_frame*)
- PyObject_New(struct sr_py_python_frame, &sr_py_python_frame_type);
-
- if (!item)
- return PyErr_NoMemory();
-
- item->frame = frame;
- if (PyList_Append(result, (PyObject *)item) < 0)
- return NULL;
-
- frame = frame->next;
- }
-
- return result;
-}
-
-int
-python_free_frame_python_list(struct sr_py_python_stacktrace *stacktrace)
-{
- int i;
- PyObject *item;
-
- for (i = 0; i < PyList_Size(stacktrace->frames); ++i)
- {
- item = PyList_GetItem(stacktrace->frames, i);
- if (!item)
- return -1;
- Py_DECREF(item);
- }
- Py_DECREF(stacktrace->frames);
-
- return 0;
-}
-
/* constructor */
PyObject *
sr_py_python_stacktrace_new(PyTypeObject *object,
@@ -214,6 +118,8 @@ sr_py_python_stacktrace_new(PyTypeObject *object,
if (!bo)
return PyErr_NoMemory();
+ bo->frame_type = &sr_py_python_frame_type;
+
const char *str = NULL;
if (!PyArg_ParseTuple(args, "|s", &str))
return NULL;
@@ -229,7 +135,7 @@ sr_py_python_stacktrace_new(PyTypeObject *object,
return NULL;
}
- bo->frames = python_frame_linked_list_to_python_list(bo->stacktrace);
+ bo->frames = frames_to_python_list((struct sr_thread *)bo->stacktrace, bo->frame_type);
}
else
{
@@ -245,7 +151,7 @@ void
sr_py_python_stacktrace_free(PyObject *object)
{
struct sr_py_python_stacktrace *this = (struct sr_py_python_stacktrace*)object;
- python_free_frame_python_list(this);
+ frames_free_python_list((struct sr_py_base_thread *)this);
this->stacktrace->frames = NULL;
sr_python_stacktrace_free(this->stacktrace);
PyObject_Del(object);
@@ -270,7 +176,7 @@ PyObject *
sr_py_python_stacktrace_dup(PyObject *self, PyObject *args)
{
struct sr_py_python_stacktrace *this = (struct sr_py_python_stacktrace*)self;
- if (python_stacktrace_prepare_linked_list(this) < 0)
+ if (frames_prepare_linked_list((struct sr_py_base_thread *)this) < 0)
return NULL;
struct sr_py_python_stacktrace *bo = (struct sr_py_python_stacktrace*)
@@ -280,39 +186,18 @@ sr_py_python_stacktrace_dup(PyObject *self, PyObject *args)
if (!bo)
return PyErr_NoMemory();
+ bo->frame_type = &sr_py_python_frame_type;
bo->stacktrace = sr_python_stacktrace_dup(this->stacktrace);
if (!bo->stacktrace)
return NULL;
- bo->frames = python_frame_linked_list_to_python_list(bo->stacktrace);
+ bo->frames = frames_to_python_list((struct sr_thread *)bo->stacktrace, bo->frame_type);
if (!bo->frames)
return NULL;
return (PyObject*)bo;
}
-PyObject *
-sr_py_python_stacktrace_to_short_text(PyObject *self, PyObject *args)
-{
- int max_frames = 0;
- if (!PyArg_ParseTuple(args, "|i", &max_frames))
- return NULL;
-
- struct sr_py_python_stacktrace *this = (struct sr_py_python_stacktrace*)self;
- if (python_stacktrace_prepare_linked_list(this) < 0)
- return NULL;
-
- char *text =
- sr_stacktrace_to_short_text((struct sr_stacktrace *)this->stacktrace, max_frames);
- if (!text)
- return NULL;
-
- PyObject *result = PyString_FromString(text);
-
- free(text);
- return result;
-}
-
/*
* No python normalization implemented yet
*
diff --git a/python/py_python_stacktrace.h b/python/py_python_stacktrace.h
index 8075344..faa5e06 100644
--- a/python/py_python_stacktrace.h
+++ b/python/py_python_stacktrace.h
@@ -34,11 +34,15 @@ extern "C" {
PyTypeObject sr_py_python_stacktrace_type;
+/* The beginning of this structure has to have the same layout as
+ * sr_py_base_thread.
+ */
struct sr_py_python_stacktrace
{
PyObject_HEAD
- PyObject *frames;
struct sr_python_stacktrace *stacktrace;
+ PyObject *frames;
+ PyTypeObject *frame_type;
};
/* constructor */
@@ -55,7 +59,6 @@ PyObject *sr_py_python_stacktrace_str(PyObject *self);
/* methods */
PyObject *sr_py_python_stacktrace_dup(PyObject *self, PyObject *args);
PyObject *sr_py_python_stacktrace_normalize(PyObject *self, PyObject *args);
-PyObject *sr_py_python_stacktrace_to_short_text(PyObject *self, PyObject *args);
#ifdef __cplusplus
--
1.7.11.7
More information about the Crash-catcher
mailing list