[SATYR PATCH] python: fix attribute deletion segfault
by Martin Milata
Previous commit 93d2ef8b730bc2659e348bce9f7ecfc902600b9d introduced a
bug where an attempt to delete a computed attribute results in a
segmentation fault.
The setters in C bindings have been modified to check whether the new
parameter is NULL and throw an exception if it is.
Signed-off-by: Martin Milata <mmilata(a)redhat.com>
---
python/py_common.c | 24 ++++++++++++++++++++++++
python/py_gdb_sharedlib.c | 6 ++++++
tests/python/koops.py | 1 +
tests/python/test_helpers.py | 1 +
4 files changed, 32 insertions(+)
diff --git a/python/py_common.c b/python/py_common.c
index 15aa108..2b4dd9b 100644
--- a/python/py_common.c
+++ b/python/py_common.c
@@ -42,6 +42,12 @@ sr_py_getter_string(PyObject *self, void *data)
int
sr_py_setter_string(PyObject *self, PyObject *rhs, void *data)
{
+ if (rhs == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute.");
+ return -1;
+ }
+
struct getset_offsets *gsoff = data;
char *newvalue = PyString_AsString(rhs);
@@ -66,6 +72,12 @@ sr_py_getter_uint32(PyObject *self, void *data)
int
sr_py_setter_uint32(PyObject *self, PyObject *rhs, void *data)
{
+ if (rhs == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute.");
+ return -1;
+ }
+
struct getset_offsets *gsoff = data;
long newvalue = PyInt_AsLong(rhs);
@@ -95,6 +107,12 @@ sr_py_getter_bool(PyObject *self, void *data)
int
sr_py_setter_bool(PyObject *self, PyObject *rhs, void *data)
{
+ if (rhs == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute.");
+ return -1;
+ }
+
struct getset_offsets *gsoff = data;
bool newvalue = PyObject_IsTrue(rhs);
@@ -116,6 +134,12 @@ sr_py_getter_uint64(PyObject *self, void *data)
int
sr_py_setter_uint64(PyObject *self, PyObject *rhs, void *data)
{
+ if (rhs == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute.");
+ return -1;
+ }
+
struct getset_offsets *gsoff = data;
unsigned long long newvalue = PyInt_AsUnsignedLongLongMask(rhs);
diff --git a/python/py_gdb_sharedlib.c b/python/py_gdb_sharedlib.c
index 4d34278..da66c79 100644
--- a/python/py_gdb_sharedlib.c
+++ b/python/py_gdb_sharedlib.c
@@ -124,6 +124,12 @@ sr_py_gdb_sharedlib_get_symbols(PyObject *self, void *data)
int
sr_py_gdb_sharedlib_set_symbols(PyObject *self, PyObject *rhs, void *data)
{
+ if (rhs == NULL)
+ {
+ PyErr_SetString(PyExc_TypeError, "Cannot delete this attribute.");
+ return -1;
+ }
+
long newvalue = PyInt_AsLong(rhs);
if (PyErr_Occurred())
return -1;
diff --git a/tests/python/koops.py b/tests/python/koops.py
index fbeb8dd..f0c6ac0 100755
--- a/tests/python/koops.py
+++ b/tests/python/koops.py
@@ -31,6 +31,7 @@ class TestKerneloops(BindingsTestCase):
## not implemented, expected to fail
#self.koops.modules = ['foo', 'bar']
#self.assertEqual(len(self.koops.modules), 2)
+ self.assertRaises(NotImplementedError, self.koops.__delattr__, 'modules')
def test_dup(self):
dup = self.koops.dup()
diff --git a/tests/python/test_helpers.py b/tests/python/test_helpers.py
index 4bd03a0..e8de55d 100644
--- a/tests/python/test_helpers.py
+++ b/tests/python/test_helpers.py
@@ -8,6 +8,7 @@ class BindingsTestCase(unittest.TestCase):
self.assertEqual(obj.__getattribute__(attr), orig_val)
obj.__setattr__(attr, new_val)
self.assertEqual(obj.__getattribute__(attr), new_val)
+ self.assertRaises(TypeError, obj.__delattr__, attr)
if __name__ == '__main__':
import sys
--
1.7.11.7
10 years, 11 months
[LIBREPORT PATCH] workflow config: use scrollbars instead of enormous window size
by Jakub Filak
Scrollbars has been chosen instead of displaying an event configuration
in a separate tab because any event option can expand dialog size to
enormous size. Therefore separate tabs requires scrollbars too.
Even more the tabs are less clear than displaying all options on a
single window.
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/gtk-helpers/event_config_dialog.c | 5 +++++
src/gtk-helpers/workflow_config_dialog.c | 11 +++++++++--
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/src/gtk-helpers/event_config_dialog.c b/src/gtk-helpers/event_config_dialog.c
index 82d07df..238c84b 100644
--- a/src/gtk-helpers/event_config_dialog.c
+++ b/src/gtk-helpers/event_config_dialog.c
@@ -202,6 +202,11 @@ config_dialog_t *create_event_config_dialog_content(event_config_t *event, GtkWi
gtk_grid_set_row_spacing(GTK_GRID(option_table), 2);
g_object_set_data(G_OBJECT(option_table), "n-rows", (gpointer)-1);
+ gtk_widget_set_hexpand(option_table, TRUE);
+ gtk_widget_set_vexpand(option_table, TRUE);
+ gtk_widget_set_halign(option_table, GTK_ALIGN_FILL);
+ gtk_widget_set_valign(option_table, GTK_ALIGN_FILL);
+
/* table to hold advanced options
* hidden in expander which is visible only if there's at least
* one advanced option
diff --git a/src/gtk-helpers/workflow_config_dialog.c b/src/gtk-helpers/workflow_config_dialog.c
index 93dd622..32be2fa 100644
--- a/src/gtk-helpers/workflow_config_dialog.c
+++ b/src/gtk-helpers/workflow_config_dialog.c
@@ -80,7 +80,7 @@ config_dialog_t *create_workflow_config_dialog(const char *workflow_name, GtkWin
NULL);
gtk_window_set_resizable(GTK_WINDOW(dialog), true);
- gtk_window_set_default_size(GTK_WINDOW(dialog), 450, -1);
+ gtk_window_set_default_size(GTK_WINDOW(dialog), 450, 450);
if (parent_window != NULL)
{
@@ -88,11 +88,18 @@ config_dialog_t *create_workflow_config_dialog(const char *workflow_name, GtkWin
gtk_window_get_icon_name(parent_window));
}
- GtkWidget *content = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ GtkWidget *scrolled = gtk_scrolled_window_new(NULL, NULL);
+ GtkWidget *content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
+ gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled), content);
+
+ GtkWidget *dialog_box = gtk_dialog_get_content_area(GTK_DIALOG(dialog));
+ gtk_box_pack_start(GTK_BOX(dialog_box), scrolled, false, true, 0);
g_events_options = NULL;
g_list_foreach(events, (GFunc)create_event_config_dialog_content_cb, content);
+ gtk_widget_show_all(GTK_WIDGET(scrolled));
+
config_dialog_t *cdialog = new_config_dialog(dialog,
g_events_options,
(config_save_fun_t)save_data_from_worfklow_dialog);
--
1.8.1.4
10 years, 11 months
[ABRT PATCH 1/3] abrt-uefioops: new service
by Denys Vlasenko
This service, once per boot, scans /sys/fs/pstore/* and crates
oops problem dirs from this data.
Signed-off-by: Denys Vlasenko <dvlasenk(a)redhat.com>
---
Makefile.am | 6 +-
init-scripts/abrt-uefioops | 79 ++++++++++++++++++++
init-scripts/abrt-uefioops.service | 12 +++
po/POTFILES.in | 4 +-
src/hooks/Makefile.am | 37 +++++++++-
src/hooks/abrt-harvest-uefioops.in | 24 ++++++
src/hooks/abrt-merge-uefioops.c | 148 +++++++++++++++++++++++++++++++++++++
7 files changed, 304 insertions(+), 6 deletions(-)
create mode 100644 init-scripts/abrt-uefioops
create mode 100644 init-scripts/abrt-uefioops.service
create mode 100644 src/hooks/abrt-harvest-uefioops.in
create mode 100644 src/hooks/abrt-merge-uefioops.c
diff --git a/Makefile.am b/Makefile.am
index cc820ee..0eecc60 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -34,14 +34,16 @@ if HAVE_SYSTEMD
init-scripts/abrt-ccpp.service \
init-scripts/abrt-oops.service \
init-scripts/abrt-xorg.service \
- init-scripts/abrt-vmcore.service
+ init-scripts/abrt-vmcore.service \
+ init-scripts/abrt-uefioops.service
else
sysv_initdir = $(sysconfdir)/rc.d/init.d/
sysv_init_SCRIPTS = init-scripts/abrtd \
init-scripts/abrt-ccpp \
init-scripts/abrt-oops \
init-scripts/abrt-xorg \
- init-scripts/abrt-vmcore
+ init-scripts/abrt-vmcore \
+ init-scripts/abrt-uefioops
endif
RPM_DIRS = --define "_sourcedir `pwd`" \
diff --git a/init-scripts/abrt-uefioops b/init-scripts/abrt-uefioops
new file mode 100644
index 0000000..663e24a
--- /dev/null
+++ b/init-scripts/abrt-uefioops
@@ -0,0 +1,79 @@
+#!/bin/bash
+# Harvest UEFI-saved oopses for ABRT
+#
+# chkconfig: 35 82 16
+# description: Collects UEFI-saved oopses for ABRT
+### BEGIN INIT INFO
+# Provides: abrt-uefioops
+# Required-Start: $abrtd
+# Default-Stop: 0 1 2 6
+# Default-Start: 3 5
+# Short-Description: Collects UEFI-saved oopses for ABRT
+# Description: Collects UEFI-saved oopses for ABRT
+### END INIT INFO
+
+# Source function library.
+. /etc/rc.d/init.d/functions
+
+LOCK="/var/lock/subsys/abrt-uefioops"
+HARVEST_CMD="/usr/sbin/abrt-harvest-uefioops"
+
+RETVAL=0
+
+check() {
+ # Check that we're a privileged user
+ [ "`id -u`" = 0 ] || exit 4
+}
+
+start() {
+ check
+ "$HARVEST_CMD"
+ RETVAL=$?
+ [ $RETVAL -eq 0 ] && touch -- "$LOCK"
+ return $RETVAL
+}
+
+stop() {
+ check
+ rm -f -- "$LOCK"
+ return 0
+}
+
+restart() {
+ stop
+ start
+}
+
+reload() {
+ restart
+}
+
+case "$1" in
+start)
+ start
+ ;;
+stop)
+ stop
+ ;;
+reload)
+ reload
+ ;;
+force-reload)
+ echo "$0: Unimplemented feature."
+ RETVAL=3
+ ;;
+restart)
+ restart
+ ;;
+condrestart)
+ test -f "$LOCK" && restart
+ ;;
+status)
+ test -f "$LOCK" && RETVAL=0 || RETVAL=3
+ ;;
+*)
+ echo $"Usage: $0 {start|stop|status|restart|condrestart|reload|force-reload}"
+ RETVAL=2
+esac
+
+exit $RETVAL
diff --git a/init-scripts/abrt-uefioops.service b/init-scripts/abrt-uefioops.service
new file mode 100644
index 0000000..cee4296
--- /dev/null
+++ b/init-scripts/abrt-uefioops.service
@@ -0,0 +1,12 @@
+[Unit]
+Description=Collect UEFI-saved oopses for ABRT
+After=abrtd.service
+Requisite=abrtd.service
+
+[Service]
+Type=oneshot
+ExecStart=/usr/sbin/abrt-harvest-uefioops
+RemainAfterExit=yes
+
+[Install]
+WantedBy=multi-user.target
diff --git a/po/POTFILES.in b/po/POTFILES.in
index b057a3d..26b595e 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -35,13 +35,15 @@ src/plugins/collect_xsession_errors.xml.in
src/plugins/https-utils.c
src/plugins/bodhi.c
+src/hooks/abrt-merge-uefioops.c
+
src/cli/abrt-cli.c
src/cli/list.c
src/cli/status.c
+
src/plugins/analyze_CCpp.xml.in
src/plugins/analyze_VMcore.xml.in
src/plugins/collect_GConf.xml.in
src/plugins/collect_vimrc_system.xml.in
src/plugins/collect_vimrc_user.xml.in
src/plugins/post_report.xml.in
-
diff --git a/src/hooks/Makefile.am b/src/hooks/Makefile.am
index 9f65d62..de97a88 100644
--- a/src/hooks/Makefile.am
+++ b/src/hooks/Makefile.am
@@ -12,7 +12,11 @@ dist_pluginsconf_DATA = \
sbin_SCRIPTS = \
abrt-install-ccpp-hook \
- abrt-harvest-vmcore
+ abrt-harvest-vmcore \
+ abrt-harvest-uefioops
+
+bin_PROGRAMS = \
+ abrt-merge-uefioops
libexec_PROGRAMS = abrt-hook-ccpp
@@ -32,10 +36,32 @@ abrt_hook_ccpp_LDADD = \
../lib/libabrt.la \
$(LIBREPORT_LIBS)
-pyhook_PYTHON = abrt_exception_handler.py abrt.pth
+# abrt-merge-uefioops
+abrt_merge_uefioops_SOURCES = \
+ abrt-merge-uefioops.c
+abrt_merge_uefioops_CPPFLAGS = \
+ -I$(srcdir)/../include \
+ -I$(srcdir)/../lib \
+ -DVAR_RUN=\"$(VAR_RUN)\" \
+ -DPLUGINS_CONF_DIR=\"$(PLUGINS_CONF_DIR)\" \
+ -DDEFAULT_DUMP_DIR_MODE=$(DEFAULT_DUMP_DIR_MODE) \
+ $(GLIB_CFLAGS) \
+ $(LIBREPORT_CFLAGS) \
+ -D_GNU_SOURCE
+abrt_merge_uefioops_LDADD = \
+ ../lib/libabrt.la \
+ $(LIBREPORT_LIBS)
+
+DEFS = -DLOCALEDIR=\"$(localedir)\" @DEFS@
+
+pyhook_PYTHON = \
+ abrt_exception_handler.py \
+ abrt.pth
+
EXTRA_DIST = abrt_exception_handler.py.in \
abrt-install-ccpp-hook.in \
- abrt-harvest-vmcore.in
+ abrt-harvest-vmcore.in \
+ abrt-harvest-uefioops.in
CLEANFILES := $(notdir $(wildcard *~)) $(notdir $(wildcard *\#)) $(notdir $(wildcard \.\#*)) $(notdir $(wildcard *.pyc)) $(man1_MANS)
@@ -63,3 +89,8 @@ abrt-harvest-vmcore: abrt-harvest-vmcore.in
sed -e s,\@CONF_DIR\@,\$(CONF_DIR)\,g \
-e s,\@DEFAULT_DUMP_LOCATION\@,$(DEFAULT_DUMP_LOCATION),g \
$< >$@
+
+abrt-harvest-uefioops: abrt-harvest-uefioops.in
+ sed -e s,\@CONF_DIR\@,\$(CONF_DIR)\,g \
+ -e s,\@DEFAULT_DUMP_LOCATION\@,$(DEFAULT_DUMP_LOCATION),g \
+ $< >$@
diff --git a/src/hooks/abrt-harvest-uefioops.in b/src/hooks/abrt-harvest-uefioops.in
new file mode 100644
index 0000000..9f63256
--- /dev/null
+++ b/src/hooks/abrt-harvest-uefioops.in
@@ -0,0 +1,24 @@
+#!/bin/sh
+#
+# This script is meant to be run once at system startup after abrtd is up
+# and running. It scans /sys/fs/pstore/*, reconstructs oops text(s)
+# from these files, creates ABRT problem directories from them,
+# then removes the files (UEFI storage is a limited resource).
+#
+
+# Wait for abrtd to start. Give it at least 1 second to initialize.
+i=10
+while ! pidof abrtd >/dev/null; do
+ if test $((i--)) = 0; then
+ exit 1
+ fi
+ sleep 1
+done
+sleep 1
+
+cd /sys/fs/pstore 2>/dev/null || exit 0
+
+abrt-merge-uefioops -o * | abrt-dump-oops -D
+if test $? = 0; then
+ abrt-merge-uefioops -d *
+fi
diff --git a/src/hooks/abrt-merge-uefioops.c b/src/hooks/abrt-merge-uefioops.c
new file mode 100644
index 0000000..53f9fd1
--- /dev/null
+++ b/src/hooks/abrt-merge-uefioops.c
@@ -0,0 +1,148 @@
+/*
+ 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 "libabrt.h"
+
+struct oops_text {
+ unsigned panic_no;
+ unsigned part_no;
+ const char *filename;
+ char *text;
+};
+
+static
+struct oops_text *parse_file(const char *filename)
+{
+ FILE *fp = fopen(filename, "r");
+ if (!fp)
+ return NULL;
+
+ char buffer[16 * 1024];
+
+ struct oops_text *ot = NULL;
+
+ if (!fgets(buffer, sizeof(buffer), fp))
+ goto ret;
+ unsigned n1, n2;
+ int n = sscanf(buffer, "Panic#%u Part%u\n", &n1, &n2);
+ if (n != 2)
+ goto ret;
+
+ ot = xzalloc(sizeof(*ot));
+ ot->filename = filename;
+ ot->panic_no = n1;
+ ot->part_no = n2;
+
+ size_t sz = fread(buffer, 1, sizeof(buffer), fp);
+ ot->text = strndup(buffer, sz);
+
+ ret:
+ fclose(fp);
+ return ot;
+}
+
+static
+int compare_oops_texts(const void *a, const void *b)
+{
+ struct oops_text *aa = *(struct oops_text **)a;
+ struct oops_text *bb = *(struct oops_text **)b;
+ if (aa->panic_no < bb->panic_no)
+ return -1;
+ if (aa->panic_no > bb->panic_no)
+ return 1;
+ if (aa->part_no < bb->part_no)
+ return -1;
+ return (aa->part_no > bb->part_no);
+}
+
+int main(int argc, char **argv)
+{
+ /* I18n */
+ setlocale(LC_ALL, "");
+#if ENABLE_NLS
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+#endif
+
+ abrt_init(argv);
+
+ /* Can't keep these strings/structs static: _() doesn't support that */
+ const char *program_usage_string = _(
+ "& [-v] [-od] FILE...\n"
+ "\n"
+ "Scans files for split oops message. Can print and/or delete them."
+ );
+ enum {
+ OPT_v = 1 << 0,
+ OPT_o = 1 << 1,
+ OPT_d = 1 << 2,
+ };
+ /* Keep enum above and order of options below in sync! */
+ struct options program_options[] = {
+ OPT__VERBOSE(&g_verbose),
+ OPT_BOOL('o', NULL, NULL, _("Print found oopses")),
+ OPT_BOOL('d', NULL, NULL, _("Delete files with found oopses")),
+ OPT_END()
+ };
+ unsigned opts = parse_opts(argc, argv, program_options, program_usage_string);
+
+ export_abrt_envvars(0);
+
+ struct oops_text **v = xzalloc(sizeof(v[0]));
+ int i = 0;
+
+ while (*argv)
+ {
+ v[i] = parse_file(*argv);
+ if (v[i])
+ {
+ v = xrealloc(v, (++i + 1) * sizeof(v[0]));
+ v[i] = NULL;
+ }
+ argv++;
+ }
+
+ if (i == 0) /* nothing was found */
+ return 0;
+
+ qsort(v, i, sizeof(v[0]), compare_oops_texts);
+
+ if (opts & OPT_o)
+ {
+ struct oops_text **vv = v;
+ while (*vv)
+ {
+ struct oops_text *cur_oops = *vv;
+ fputs(cur_oops->text, stdout);
+ vv++;
+ }
+ }
+
+ if (opts & OPT_d)
+ {
+ struct oops_text **vv = v;
+ while (*vv)
+ {
+ struct oops_text *cur_oops = *vv;
+ if (unlink(cur_oops->filename) != 0)
+ perror_msg("Can't unlink '%s'", cur_oops->filename);
+ vv++;
+ }
+ }
+
+ return 0;
+}
--
1.8.1.4
10 years, 11 months
[GNOME-ABRT PATCH] Show HTML titles of URLs from reported_to element
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
configure.ac | 1 +
gnome-abrt.spec.in | 1 +
pylintrc | 2 +-
src/gnome-abrt | 7 ++
src/gnome_abrt/Makefile.am | 2 +-
src/gnome_abrt/problems.py | 41 +++++++--
src/gnome_abrt/url/Makefile.am | 3 +
src/gnome_abrt/url/__init__.py | 29 ++++++
src/gnome_abrt/url/gliburltitle.py | 178 +++++++++++++++++++++++++++++++++++++
src/gnome_abrt/url/urltitle.py | 139 +++++++++++++++++++++++++++++
src/gnome_abrt/views.py | 8 +-
11 files changed, 398 insertions(+), 13 deletions(-)
create mode 100644 src/gnome_abrt/url/Makefile.am
create mode 100644 src/gnome_abrt/url/__init__.py
create mode 100644 src/gnome_abrt/url/gliburltitle.py
create mode 100644 src/gnome_abrt/url/urltitle.py
diff --git a/configure.ac b/configure.ac
index 4a924ce..8f1a567 100644
--- a/configure.ac
+++ b/configure.ac
@@ -100,6 +100,7 @@ AC_CONFIG_FILES([
src/Makefile
src/gnome_abrt/Makefile
src/gnome_abrt/wrappers/Makefile
+ src/gnome_abrt/url/Makefile
po/Makefile.in
])
diff --git a/gnome-abrt.spec.in b/gnome-abrt.spec.in
index 5ed9a17..df30ac5 100644
--- a/gnome-abrt.spec.in
+++ b/gnome-abrt.spec.in
@@ -89,6 +89,7 @@ gtk-update-icon-cache %{_datadir}/icons/hicolor &>/dev/null || :
%files -f %{name}.lang
%doc COPYING
%{python_sitearch}/gnome_abrt
+%{python_sitearch}/gnome_abrt/url
%{_datadir}/%{name}
%{_bindir}/%{name}
%{_datadir}/applications/*
diff --git a/pylintrc b/pylintrc
index b5d55c5..fdb32d3 100644
--- a/pylintrc
+++ b/pylintrc
@@ -33,7 +33,7 @@ load-plugins=
# can either give multiple identifier separated by comma (,) or put this option
# multiple time (only on the command line, not in the configuration file where
# it should appear only once).
-disable=C0111,W0212,R0201,R0903,I0011,W0603,W0622,I0001
+disable=C0111,W0212,R0201,R0903,R0904,I0011,W0603,W0622,I0001
[REPORTS]
diff --git a/src/gnome-abrt b/src/gnome-abrt
index 633eb3a..d3417d2 100755
--- a/src/gnome-abrt
+++ b/src/gnome-abrt
@@ -34,6 +34,7 @@ from gi.repository import Gio
# gnome-abrt
import gnome_abrt
+import gnome_abrt.url
from gnome_abrt.views import OopsWindow
from gnome_abrt.controller import Controller
from gnome_abrt.signals import glib_sigchld_signal_handler
@@ -45,6 +46,8 @@ from gnome_abrt.l10n import _
from gnome_abrt.wrappers import show_events_list_dialog
from gnome_abrt.config import get_configuration
from gnome_abrt.dialogs import show_report_problem_with_abrt
+from gnome_abrt.url.gliburltitle import (GetURLTitleSourcePool,
+ GetURLTitleSourceCache)
# dbus
import dbus
@@ -54,6 +57,7 @@ from dbus.mainloop.glib import DBusGMainLoop
GNOME_ABRT_APPLICATION_ID = 'org.freedesktop.GnomeAbrt'
GNOME_ABRT_INTERFACE = 'org.freedesktop.GnomeAbrt'
GNOME_ABRT_OBJECT_PATH = '/org/freedesktop/GnomeAbrt'
+GNOME_ABRT_URL_POOL_CAPACITY = 10
# because of https://bugzilla.gnome.org/show_bug.cgi?id=682331
@@ -148,6 +152,9 @@ class OopsApplication(Gtk.Application):
self.set_flags(Gio.ApplicationFlags.HANDLES_COMMAND_LINE)
self.gcontext = None
self.source = None
+ self._url_pool = GetURLTitleSourcePool(GNOME_ABRT_URL_POOL_CAPACITY)
+ self._url_cache = GetURLTitleSourceCache(self._url_pool)
+ gnome_abrt.url.set_async_worker(self._url_cache.get_url_title_async)
#pylint: disable=W0613
def _parse_command_line(self, sender, gcmdargs):
diff --git a/src/gnome_abrt/Makefile.am b/src/gnome_abrt/Makefile.am
index 60496f9..0f0e557 100644
--- a/src/gnome_abrt/Makefile.am
+++ b/src/gnome_abrt/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = wrappers
+SUBDIRS = wrappers url
gnome_abrtexecdir = $(pyexecdir)/gnome_abrt
diff --git a/src/gnome_abrt/problems.py b/src/gnome_abrt/problems.py
index 4bf7695..1d3974e 100644
--- a/src/gnome_abrt/problems.py
+++ b/src/gnome_abrt/problems.py
@@ -19,6 +19,7 @@ import datetime
import logging
# gnome-abrt
+import gnome_abrt.url
from gnome_abrt.application import find_application
from gnome_abrt.errors import (InvalidProblem,
UnavailableSource,
@@ -70,10 +71,40 @@ class Problem:
MSG = "MSG"
BTHASH = "BTHASH"
- def __init__(self, title, rtype, data):
- self.title = title
- self.rtype = rtype
- self.data = data
+ def __init__(self, problem, name, rtype, data):
+ self._problem = problem
+ self._name = name
+ self._title = name
+ self._rtype = rtype
+ self._data = data
+ self._url_done = False
+
+ def _update_title_async_cb(self, result, unused_userdata):
+ if result[1]:
+ self._title = result[1]
+ self._problem.source.notify(ProblemSource.CHANGED_PROBLEM,
+ self._problem)
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def rtype(self):
+ return self._rtype
+
+ @property
+ def data(self):
+ return self._data
+
+ @property
+ def title(self):
+ if self._rtype == Problem.Submission.URL and not self._url_done:
+ self._url_done = True
+ gnome_abrt.url.get_url_title_async(self._data,
+ self._update_title_async_cb, None)
+
+ return self._title
def __init__(self, problem_id, source):
@@ -226,7 +257,7 @@ class Problem:
i += 1
self.submission.append(
- Problem.Submission(pfx, typ, line[i:]))
+ Problem.Submission(self, pfx, typ, line[i:]))
return self.submission
diff --git a/src/gnome_abrt/url/Makefile.am b/src/gnome_abrt/url/Makefile.am
new file mode 100644
index 0000000..195ebec
--- /dev/null
+++ b/src/gnome_abrt/url/Makefile.am
@@ -0,0 +1,3 @@
+gnome_abrt_url_PYTHON = __init__.py urltitle.py gliburltitle.py
+
+gnome_abrt_urldir = $(pyexecdir)/gnome_abrt/url
diff --git a/src/gnome_abrt/url/__init__.py b/src/gnome_abrt/url/__init__.py
new file mode 100644
index 0000000..5b77759
--- /dev/null
+++ b/src/gnome_abrt/url/__init__.py
@@ -0,0 +1,29 @@
+# coding=UTF-8
+
+## Copyright (C) 2013 ABRT team <crash-catcher(a)lists.fedorahosted.org>
+## 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, Suite 500, Boston, MA 02110-1335 USA
+
+from gnome_abrt.url import gliburltitle
+
+__ASYNC_WORKER = gliburltitle.get_url_title_async
+
+def set_async_worker(worker):
+ global __ASYNC_WORKER
+ __ASYNC_WORKER = worker
+
+def get_url_title_async(url, callback, user_data):
+ __ASYNC_WORKER(url, callback, user_data)
diff --git a/src/gnome_abrt/url/gliburltitle.py b/src/gnome_abrt/url/gliburltitle.py
new file mode 100644
index 0000000..9a6f6e6
--- /dev/null
+++ b/src/gnome_abrt/url/gliburltitle.py
@@ -0,0 +1,178 @@
+#!/usr/bin/env python
+# coding=UTF-8
+
+## Copyright (C) 2013 ABRT team <crash-catcher(a)lists.fedorahosted.org>
+## 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, Suite 500, Boston, MA 02110-1335 USA
+
+import sys
+from Queue import Queue
+
+# pygobject
+#pylint: disable=E0611
+from gi.repository import GLib
+
+from gnome_abrt.url.urltitle import GetURLTitleThread
+
+
+def get_url_title_async(url, readycallback, userdata, context=None):
+ """Gets url's title assynchronously
+ """
+
+ if context is None:
+ context = GLib.main_context_default()
+
+ source = GetURLTitleThreadSource(url, readycallback, userdata)
+ #pylint: disable=E1101
+ source.attach(context)
+
+
+class GetURLTitleThreadSource(GLib.Source):
+ """Runs thread and waits until the thread does not return the url's title
+ """
+
+ #pylint: disable=W0613
+ def __new__(cls, *args):
+ return GLib.Source.__new__(cls)
+
+ def __init__(self, url, readycallback, userdata):
+ GLib.Source.__init__(self)
+
+ self._queue = Queue()
+ self._readycallback = readycallback
+ self._userdata = userdata
+ self._resolver = GetURLTitleThread(url, self._queue)
+ self._resolver.start()
+
+ def _is_ready(self):
+ return not self._queue.empty()
+
+ def prepare(self, *args):
+ return (self._is_ready(), 10)
+
+ def check(self, *args):
+ return self._is_ready()
+
+ def dispatch(self, *args):
+ if not self._is_ready():
+ raise RuntimeError("GetURLHTMLTitleThreadSource.dispatch()"
+ " called but result is not ready yet, or already consumed.")
+
+ # An attempty to destroy the resolver's thread ASAP
+ self._resolver = None
+
+ self._readycallback(self._queue.get(), self._userdata)
+
+ # Destroy this source
+ return False
+
+ def finalize(self, *args):
+ pass
+
+
+class GetURLTitleSourcePool(object):
+ """Pool for reducing number of running threads at time
+ """
+
+ def __init__(self, capacity):
+ self._capacity = capacity
+ self._running = 0
+ self._defered = list()
+
+ def get_url_title_async(self, url, readycallback, userdata):
+ if self._running == self._capacity:
+ self._defer_request(url, readycallback, userdata)
+ else:
+ self._start_resolving(url, readycallback, userdata)
+
+ def _defer_request(self, url, readycallback, userdata):
+ self._defered.append((url, readycallback, userdata))
+
+ def _start_resolving(self, url, readycallback, userdata):
+ self._running += 1
+ get_url_title_async(url, self._resolving_done,
+ (readycallback, userdata))
+
+ def _resolving_done(self, result, userdata):
+ try:
+ userdata[0](result, userdata[1])
+ finally:
+ self._running -= 1
+ if len(self._defered):
+ url, readycallback, userdata = self._defered.pop()
+ self._start_resolving(url, readycallback, userdata)
+
+
+class GetURLTitleSourceCache(object):
+ """Asynchronous cache for URL titles
+ """
+
+ def __init__(self, worker, max_size=1024):
+ self._worker = worker
+ self._max_size = max_size
+ self._cache = dict()
+ # The oldest is on the top
+ self._stamp = []
+
+ def get_url_title_async(self, url, readycallback, userdata):
+ if url in self._cache:
+ # Move url at the end
+ self._stamp.remove(url)
+ self._stamp.append(url)
+ # Callers expect that result will be delivered asynchronously
+ GLib.timeout_add(1,
+ lambda unused: readycallback((url, self._cache[url]), userdata),
+ None)
+ return
+
+ self._worker.get_url_title_async(url, self._resolved,
+ (readycallback, userdata))
+
+ def _resolved(self, result, userdata):
+ url, title = result
+ if title:
+ if len(self._cache.keys()) >= self._max_size:
+ # Remove the url on the top (the oldest)
+ del self._cache[self._stamp.pop()]
+
+ self._cache[url] = title
+ self._stamp.append(url)
+
+ readycallback, data = userdata
+ readycallback(result, data)
+
+
+if __name__ == "__main__":
+ def ready(result, userdata):
+ print result[1] or result[0]
+
+ userdata["count"] = userdata["count"] - 1
+ if userdata["count"] == 0:
+ userdata["gloop"].quit()
+
+ URLS = ["http://docs.python.org/2/library/htmlparser.html"]
+
+ if len(sys.argv) > 1:
+ URLS = sys.argv[1:]
+
+ MAINLOOP = GLib.MainLoop()
+ WORKER = GetURLTitleSourcePool(2)
+ CONSUMER = {"count":len(URLS), "gloop":MAINLOOP}
+
+ for u in URLS:
+ WORKER.get_url_title_async(u, ready, CONSUMER)
+
+ MAINLOOP.run()
diff --git a/src/gnome_abrt/url/urltitle.py b/src/gnome_abrt/url/urltitle.py
new file mode 100644
index 0000000..369b1af
--- /dev/null
+++ b/src/gnome_abrt/url/urltitle.py
@@ -0,0 +1,139 @@
+#!/usr/bin/env python
+# coding=UTF-8
+
+## Copyright (C) 2013 ABRT team <crash-catcher(a)lists.fedorahosted.org>
+## 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, Suite 500, Boston, MA 02110-1335 USA
+
+import sys
+import threading
+import logging
+from urllib import urlopen
+from HTMLParser import HTMLParser, HTMLParseError
+
+
+def get_url_title(url):
+ """Returns a title of the url
+
+ Function expects that the url points to a HTML page with the title element
+ in the head element. Tries to download the page and return a value of the
+ title.
+ """
+
+ try:
+ urlio = urlopen(url)
+ except IOError as ex:
+ logging.debug("{1} ('{0}')".format(url, str(ex)))
+ return None
+
+ encoding = urlio.info().getparam('charset')
+ # Can't find any documentation but try except needed.
+ data = urlio.read()
+ if encoding:
+ try:
+ data = data.decode(encoding)
+ except UnicodeError as ex:
+ logging.debug("{1} ('{0}')".format(url, str(ex)))
+ return None
+
+ return HTMLTitleGetter.parse(data)
+
+
+class HTMLTitleGetter(HTMLParser):
+ def __init__(self):
+ HTMLParser.__init__(self)
+
+ self._tag_head = False
+ self._tag_title = False
+ self._title = None
+
+ def handle_starttag(self, tag, attrs):
+ if not self._tag_head:
+ self._tag_head = tag.lower() == "head"
+
+ if self._tag_head and not self._tag_title:
+ self._tag_title = tag.lower() == "title"
+
+ def handle_endtag(self, tag):
+ if self._tag_head:
+ self._tag_head = tag.lower() != "head"
+
+ if self._tag_head and self._tag_title:
+ self._tag_title = tag.lower() != "title"
+
+ def handle_data(self, data):
+ if self._tag_title:
+ if not self._title:
+ self._title = data
+ else:
+ self._title += data
+
+ @staticmethod
+ def parse(data):
+ tgt = HTMLTitleGetter()
+ try:
+ tgt.feed(data)
+ except HTMLParseError as ex:
+ logging.debug("{1} ('{0}')".format(data, str(ex)))
+ # Hopefully title is parsed correctly
+
+ return tgt._title
+
+
+class GetURLTitleThread(threading.Thread):
+ """Simple thread which puts url's title into a Queue
+ """
+
+ def __init__(self, url, que):
+ super(GetURLTitleThread, self).__init__()
+
+ self._url = url
+ self._que = que
+
+ def run(self):
+ title = get_url_title(self._url)
+ self._que.put((self._url, title))
+
+
+if __name__ == "__main__":
+ URLS = ["http://docs.python.org/2/library/htmlparser.html"]
+
+ THREADS = False
+ if len(sys.argv) > 1:
+ i = 1
+ if "--threads" == sys.argv[i]:
+ THREADS = True
+ i += 1
+ URLS = sys.argv[i:]
+
+ if THREADS:
+ from Queue import Queue
+ QUEUE = Queue()
+ THREADS = []
+ for u in URLS:
+ t = GetURLTitleThread(u, QUEUE)
+ t.start()
+ THREADS.append(t)
+
+ for t in THREADS:
+ t.join()
+
+ while not QUEUE.empty():
+ ORIG_URL, GOT_TITLE = QUEUE.get()
+ print GOT_TITLE or ORIG_URL
+ else:
+ for u in URLS:
+ print get_url_title(u) or u
diff --git a/src/gnome_abrt/views.py b/src/gnome_abrt/views.py
index 5c1f6e2..6c2e5a9 100644
--- a/src/gnome_abrt/views.py
+++ b/src/gnome_abrt/views.py
@@ -256,8 +256,7 @@ class OopsWindow(Gtk.ApplicationWindow):
except errors.InvalidProblem as ex:
self._remove_problem_from_storage(ex.problem_id)
logging.debug(ex.message)
-
- return
+ return
try:
if problem in self._get_selected(self._builder.tvs_problems):
@@ -266,8 +265,6 @@ class OopsWindow(Gtk.ApplicationWindow):
self._remove_problem_from_storage(ex.problem_id)
logging.debug(ex.message)
- return
-
def _reload_problems(self, source):
self._reloading = True
old_selection = self._get_selected(self._builder.tvs_problems)
@@ -318,7 +315,6 @@ class OopsWindow(Gtk.ApplicationWindow):
self._builder.tvs_problems.select_iter(pit)
self._builder.tv_problems.scroll_to_cell(path)
-
def _show_problem_links(self, submissions):
need_align = False
for sbm in submissions:
@@ -388,7 +384,7 @@ class OopsWindow(Gtk.ApplicationWindow):
if problem['not-reportable']:
self._show_problem_message(problem['not-reportable'])
elif (not problem['is_reported']
- or not any((s.title == "Bugzilla"
+ or not any((s.name == "Bugzilla"
for s in problem['submission']))):
self._show_problem_message(
_("This problem hasn't been reported to <i>Bugzilla</i> yet. "
--
1.8.1.4
10 years, 11 months
[LIBREPORT PATCH 1/2] reporter-bugzilla: support new format keyword %reporter
by Jakub Filak
Readd lost information essential for bug fixing.
Example of line added to a bug report:
reporter: libreport-2.1.3.36.g5816.dirty
Related to #155
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/plugins/bugzilla_format.conf | 1 +
src/plugins/bugzilla_format_kernel.conf | 2 +-
src/plugins/bugzilla_format_libreport.conf | 1 +
src/plugins/bugzilla_formatdup.conf | 1 +
src/plugins/reporter-bugzilla.c | 4 ++++
5 files changed, 8 insertions(+), 1 deletion(-)
diff --git a/src/plugins/bugzilla_format.conf b/src/plugins/bugzilla_format.conf
index b06e68a..f668d17 100644
--- a/src/plugins/bugzilla_format.conf
+++ b/src/plugins/bugzilla_format.conf
@@ -48,6 +48,7 @@ Additional info:: \
-analyzer,-count,-duphash,-uuid,-abrt_version,\
-username,-hostname,-os_release,-os_info,\
-time,-pid,-pwd,\
+ %reporter,\
%oneline
Truncated backtrace:: %bare_%short_backtrace
diff --git a/src/plugins/bugzilla_format_kernel.conf b/src/plugins/bugzilla_format_kernel.conf
index c32e424..e46af89 100644
--- a/src/plugins/bugzilla_format_kernel.conf
+++ b/src/plugins/bugzilla_format_kernel.conf
@@ -40,6 +40,6 @@
Description of problem:: %bare_comment
-Additional info:: %bare_backtrace
+Additional info:: %reporter, %bare_backtrace
%attach:: dmesg
diff --git a/src/plugins/bugzilla_format_libreport.conf b/src/plugins/bugzilla_format_libreport.conf
index e5b3870..40428a5 100644
--- a/src/plugins/bugzilla_format_libreport.conf
+++ b/src/plugins/bugzilla_format_libreport.conf
@@ -50,6 +50,7 @@ Additional info:: \
-analyzer,-count,-duphash,-uuid,-abrt_version,\
-username,-hostname,-os_release,-os_info,\
-time,-pid,-pwd,\
+ %reporter,\
%oneline
Truncated backtrace:: %bare_%short_backtrace
diff --git a/src/plugins/bugzilla_formatdup.conf b/src/plugins/bugzilla_formatdup.conf
index 2ec183e..99f63c2 100644
--- a/src/plugins/bugzilla_formatdup.conf
+++ b/src/plugins/bugzilla_formatdup.conf
@@ -49,4 +49,5 @@
-username,-hostname,-os_release,-os_info,\
-time,-pid,-pwd,\
-var_log_messages,\
+ %reporter,\
%oneline
diff --git a/src/plugins/reporter-bugzilla.c b/src/plugins/reporter-bugzilla.c
index e9e0a70..d0e04b6 100644
--- a/src/plugins/reporter-bugzilla.c
+++ b/src/plugins/reporter-bugzilla.c
@@ -436,6 +436,10 @@ int append_item(struct strbuf *result, const char *item_name, problem_data_t *pd
if (strcmp(item_name, "%short_backtrace") == 0)
return append_short_backtrace(result, pd, CD_TEXT_ATT_SIZE_BZ, print_item_name);
+ /* Compat with previously-existed ad-hockery: %reporter */
+ if (strcmp(item_name, "%reporter") == 0)
+ return append_text(result, "reporter", PACKAGE"-"VERSION, print_item_name);
+
/* %oneline,%multiline,%text */
bool oneline = (strcmp(item_name+1, "oneline" ) == 0);
bool multiline = (strcmp(item_name+1, "multiline") == 0);
--
1.8.1.4
10 years, 12 months
[SATYR PATCH] python: implement comparison operators
by Martin Milata
Comparison was previously implemented by means of cmp() methods. Now we
can do `f1 < f2` instead of `f1.cmp(f2) < 0`. Notably, "==" works as
expected. Related to #59.
Signed-off-by: Martin Milata <mmilata(a)redhat.com>
---
python/py_common.c | 11 +++++++++++
python/py_common.h | 6 ++++++
python/py_gdb_frame.c | 31 ++++++-------------------------
python/py_gdb_frame.h | 6 +++++-
python/py_gdb_thread.c | 33 ++++++++++-----------------------
python/py_gdb_thread.h | 4 +++-
python/py_java_frame.c | 28 ++++++----------------------
python/py_java_frame.h | 6 +++++-
python/py_java_thread.c | 33 ++++++++++-----------------------
python/py_java_thread.h | 4 +++-
python/py_koops_frame.c | 28 ++++++----------------------
python/py_koops_frame.h | 6 +++++-
python/py_python_frame.c | 28 ++++++----------------------
python/py_python_frame.h | 6 +++++-
tests/python/gdb.py | 20 ++++++++++++++------
tests/python/java.py | 22 +++++++++++++++++-----
tests/python/koops.py | 16 +++++++++++-----
tests/python/python.py | 14 +++++++++-----
18 files changed, 138 insertions(+), 164 deletions(-)
diff --git a/python/py_common.c b/python/py_common.c
index 15aa108..f441815 100644
--- a/python/py_common.c
+++ b/python/py_common.c
@@ -125,3 +125,14 @@ sr_py_setter_uint64(PyObject *self, PyObject *rhs, void *data)
MEMB_T(uint64_t, MEMB(self, gsoff->c_struct_offset), gsoff->member_offset) = newvalue;
return 0;
}
+
+int
+normalize_cmp(int n)
+{
+ if (n > 0)
+ return 1;
+ else if (n < 0)
+ return -1;
+
+ return 0;
+}
diff --git a/python/py_common.h b/python/py_common.h
index 7b9dc82..9cc39e7 100644
--- a/python/py_common.h
+++ b/python/py_common.h
@@ -119,6 +119,12 @@ int sr_py_setter_bool(PyObject *self, PyObject *rhs, void *data);
PyObject *sr_py_getter_uint64(PyObject *self, void *data);
int sr_py_setter_uint64(PyObject *self, PyObject *rhs, void *data);
+/*
+ * Satyr's comparison functions return arbitrary numbers, while python
+ * requires the result to be in {-1, 0, 1}.
+ */
+int normalize_cmp(int n);
+
#ifdef __cplusplus
}
#endif
diff --git a/python/py_gdb_frame.c b/python/py_gdb_frame.c
index 6bfd700..48b027e 100644
--- a/python/py_gdb_frame.c
+++ b/python/py_gdb_frame.c
@@ -50,21 +50,12 @@
"Checks whether the frame represents a call to " \
"a function with given name from a given file."
-#define f_cmp_doc "Usage: frame.cmp(frame2, compare_number)\n" \
- "frame2: satyr.Frame - another frame to compare\n" \
- "compare_number: boolean - whether to compare also thread numbers\n" \
- "Returns: integer - distance\n" \
- "Compares frame to frame2. Returns 0 if frame = frame2, " \
- "<0 if frame is 'less' than frame2, >0 if frame is 'more' " \
- "than frame2."
-
static PyMethodDef
frame_methods[] =
{
/* methods */
{ "dup", sr_py_gdb_frame_dup, METH_NOARGS, f_dup_doc },
- { "cmp", sr_py_gdb_frame_cmp, METH_VARARGS, f_cmp_doc },
{ "calls_func", sr_py_gdb_frame_calls_func, METH_VARARGS, f_calls_func_doc },
{ "calls_func_in_file", sr_py_gdb_frame_calls_func_in_file, METH_VARARGS, f_calls_func_in_file_doc },
{ NULL },
@@ -143,7 +134,7 @@ sr_py_gdb_frame_type =
NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
- NULL, /* tp_compare */
+ sr_py_gdb_frame_cmp, /* tp_compare */
NULL, /* tp_repr */
NULL, /* tp_as_number */
NULL, /* tp_as_sequence */
@@ -262,23 +253,13 @@ sr_py_gdb_frame_dup(PyObject *self, PyObject *args)
return (PyObject*)fo;
}
-PyObject *
-sr_py_gdb_frame_cmp(PyObject *self, PyObject *args)
+int
+sr_py_gdb_frame_cmp(PyObject *self, PyObject *other)
{
- PyObject *compare_to;
- int compare_number;
- if (!PyArg_ParseTuple(args,
- "O!i",
- &sr_py_gdb_frame_type,
- &compare_to,
- &compare_number))
- {
- return NULL;
- }
-
struct sr_gdb_frame *f1 = ((struct sr_py_gdb_frame*)self)->frame;
- struct sr_gdb_frame *f2 = ((struct sr_py_gdb_frame*)compare_to)->frame;
- return Py_BuildValue("i", sr_gdb_frame_cmp(f1, f2, compare_number));
+ struct sr_gdb_frame *f2 = ((struct sr_py_gdb_frame*)other)->frame;
+
+ return normalize_cmp(sr_gdb_frame_cmp(f1, f2, true));
}
PyObject *
diff --git a/python/py_gdb_frame.h b/python/py_gdb_frame.h
index 4926014..e0ac90c 100644
--- a/python/py_gdb_frame.h
+++ b/python/py_gdb_frame.h
@@ -56,9 +56,13 @@ void sr_py_gdb_frame_free(PyObject *object);
*/
PyObject *sr_py_gdb_frame_str(PyObject *self);
+/**
+ * cmp
+ */
+int sr_py_gdb_frame_cmp(PyObject *self, PyObject *other);
+
/* methods */
PyObject *sr_py_gdb_frame_dup(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_cmp(PyObject *self, PyObject *args);
PyObject *sr_py_gdb_frame_calls_func(PyObject *self, PyObject *args);
PyObject *sr_py_gdb_frame_calls_func_in_file(PyObject *self, PyObject *args);
diff --git a/python/py_gdb_thread.c b/python/py_gdb_thread.c
index 1af6108..3f47043 100644
--- a/python/py_gdb_thread.c
+++ b/python/py_gdb_thread.c
@@ -17,13 +17,6 @@
"Clones the thread object. All new structures are independent " \
"on the original object."
-#define t_cmp_doc "Usage: thread.cmp(thread2)\n" \
- "thread2: satyr.Thread - another thread to compare" \
- "Returns: integer - distance" \
- "Compares thread to thread2. Returns 0 if thread = thread2, " \
- "<0 if thread is 'less' than thread2, >0 if thread is 'more' " \
- "than thread2."
-
#define t_quality_counts_doc "Usage: thread.quality_counts()\n" \
"Returns: tuple (ok, all) - ok representing number of " \
"'good' frames, all representing total number of frames\n" \
@@ -44,7 +37,6 @@ static PyMethodDef
gdb_thread_methods[] =
{
/* methods */
- { "cmp", sr_py_gdb_thread_cmp, METH_VARARGS, t_cmp_doc },
{ "dup", sr_py_gdb_thread_dup, METH_NOARGS, t_dup_doc },
{ "quality_counts", sr_py_gdb_thread_quality_counts, METH_NOARGS, t_quality_counts_doc },
{ "quality", sr_py_gdb_thread_quality, METH_NOARGS, t_quality_doc },
@@ -85,7 +77,7 @@ PyTypeObject sr_py_gdb_thread_type =
NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
- NULL, /* tp_compare */
+ (cmpfunc)sr_py_gdb_thread_cmp, /* tp_compare */
NULL, /* tp_repr */
NULL, /* tp_as_number */
NULL, /* tp_as_sequence */
@@ -331,22 +323,17 @@ sr_py_gdb_thread_dup(PyObject *self, PyObject *args)
return (PyObject *)to;
}
-PyObject *
-sr_py_gdb_thread_cmp(PyObject *self, PyObject *args)
+int
+sr_py_gdb_thread_cmp(struct sr_py_gdb_thread *self, struct sr_py_gdb_thread *other)
{
- struct sr_py_gdb_thread *this = (struct sr_py_gdb_thread *)self;
- PyObject *compare_to;
- if (!PyArg_ParseTuple(args, "O!", &sr_py_gdb_thread_type, &compare_to))
- return NULL;
-
- struct sr_py_gdb_thread *cmp_to = (struct sr_py_gdb_thread *)compare_to;
-
- if (thread_prepare_linked_list(this) < 0)
- return NULL;
- if (thread_prepare_linked_list(cmp_to) < 0)
- return NULL;
+ if (thread_prepare_linked_list(self) < 0
+ || thread_prepare_linked_list(other) < 0)
+ {
+ /* exception is already set */
+ return -1;
+ }
- return Py_BuildValue("i", sr_gdb_thread_cmp(this->thread, cmp_to->thread));
+ return normalize_cmp(sr_gdb_thread_cmp(self->thread, other->thread));
}
PyObject *
diff --git a/python/py_gdb_thread.h b/python/py_gdb_thread.h
index c2c4611..00c32b9 100644
--- a/python/py_gdb_thread.h
+++ b/python/py_gdb_thread.h
@@ -57,9 +57,11 @@ 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_cmp(PyObject *self, PyObject *args);
PyObject *sr_py_gdb_thread_quality_counts(PyObject *self, PyObject *args);
PyObject *sr_py_gdb_thread_quality(PyObject *self, PyObject *args);
PyObject *sr_py_gdb_thread_format_funs(PyObject *self, PyObject *args);
diff --git a/python/py_java_frame.c b/python/py_java_frame.c
index 507f978..d923fb5 100644
--- a/python/py_java_frame.c
+++ b/python/py_java_frame.c
@@ -34,20 +34,12 @@
"Clones the frame object. All new structures are independent " \
"on the original object."
-#define f_cmp_doc "Usage: frame.cmp(frame2)\n" \
- "frame2: satyr.Frame - another frame to compare\n" \
- "Returns: integer - distance\n" \
- "Compares frame to frame2. Returns 0 if frame = frame2, " \
- "<0 if frame is 'less' than frame2, >0 if frame is 'more' " \
- "than frame2."
-
static PyMethodDef
frame_methods[] =
{
/* methods */
{ "dup", sr_py_java_frame_dup, METH_NOARGS, f_dup_doc },
- { "cmp", sr_py_java_frame_cmp, METH_VARARGS, f_cmp_doc },
{ NULL },
};
@@ -90,7 +82,7 @@ sr_py_java_frame_type =
NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
- NULL, /* tp_compare */
+ sr_py_java_frame_cmp, /* tp_compare */
NULL, /* tp_repr */
NULL, /* tp_as_number */
NULL, /* tp_as_sequence */
@@ -229,19 +221,11 @@ sr_py_java_frame_dup(PyObject *self, PyObject *args)
return (PyObject*)fo;
}
-PyObject *
-sr_py_java_frame_cmp(PyObject *self, PyObject *args)
+int
+sr_py_java_frame_cmp(PyObject *self, PyObject *other)
{
- PyObject *compare_to;
- if (!PyArg_ParseTuple(args,
- "O!",
- &sr_py_java_frame_type,
- &compare_to))
- {
- return NULL;
- }
-
struct sr_java_frame *f1 = ((struct sr_py_java_frame*)self)->frame;
- struct sr_java_frame *f2 = ((struct sr_py_java_frame*)compare_to)->frame;
- return Py_BuildValue("i", sr_java_frame_cmp(f1, f2));
+ struct sr_java_frame *f2 = ((struct sr_py_java_frame*)other)->frame;
+
+ return normalize_cmp(sr_java_frame_cmp(f1, f2));
}
diff --git a/python/py_java_frame.h b/python/py_java_frame.h
index fead53a..c71d655 100644
--- a/python/py_java_frame.h
+++ b/python/py_java_frame.h
@@ -56,9 +56,13 @@ void sr_py_java_frame_free(PyObject *object);
*/
PyObject *sr_py_java_frame_str(PyObject *self);
+/**
+ * cmp
+ */
+int sr_py_java_frame_cmp(PyObject *self, PyObject *other);
+
/* methods */
PyObject *sr_py_java_frame_dup(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_cmp(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
diff --git a/python/py_java_thread.c b/python/py_java_thread.c
index d70af6e..dc3bd5f 100644
--- a/python/py_java_thread.c
+++ b/python/py_java_thread.c
@@ -18,13 +18,6 @@
"Clones the thread object. All new structures are independent " \
"on the original object."
-#define t_cmp_doc "Usage: thread.cmp(thread2)\n" \
- "thread2: satyr.JavaThread - another thread to compare" \
- "Returns: integer - distance" \
- "Compares thread to thread2. Returns 0 if thread = thread2, " \
- "<0 if thread is 'less' than thread2, >0 if thread is 'more' " \
- "than thread2."
-
#define t_quality_counts_doc "Usage: thread.quality_counts()\n" \
"Returns: tuple (ok, all) - ok representing number of " \
"'good' frames, all representing total number of frames\n" \
@@ -45,7 +38,6 @@ static PyMethodDef
java_thread_methods[] =
{
/* methods */
- { "cmp", sr_py_java_thread_cmp, METH_VARARGS, t_cmp_doc },
{ "dup", sr_py_java_thread_dup, METH_NOARGS, t_dup_doc },
{ "quality_counts", sr_py_java_thread_quality_counts, METH_NOARGS, t_quality_counts_doc },
{ "quality", sr_py_java_thread_quality, METH_NOARGS, t_quality_doc },
@@ -86,7 +78,7 @@ PyTypeObject sr_py_java_thread_type =
NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
- NULL, /* tp_compare */
+ (cmpfunc)sr_py_java_thread_cmp, /* tp_compare */
NULL, /* tp_repr */
NULL, /* tp_as_number */
NULL, /* tp_as_sequence */
@@ -301,22 +293,17 @@ sr_py_java_thread_dup(PyObject *self, PyObject *args)
return (PyObject *)to;
}
-PyObject *
-sr_py_java_thread_cmp(PyObject *self, PyObject *args)
+int
+sr_py_java_thread_cmp(struct sr_py_java_thread *self, struct sr_py_java_thread *other)
{
- struct sr_py_java_thread *this = (struct sr_py_java_thread *)self;
- PyObject *compare_to;
- if (!PyArg_ParseTuple(args, "O!", &sr_py_java_thread_type, &compare_to))
- return NULL;
-
- struct sr_py_java_thread *cmp_to = (struct sr_py_java_thread *)compare_to;
-
- if (java_thread_prepare_linked_list(this) < 0)
- return NULL;
- if (java_thread_prepare_linked_list(cmp_to) < 0)
- return NULL;
+ if (java_thread_prepare_linked_list(self) < 0
+ || java_thread_prepare_linked_list(other) < 0)
+ {
+ /* exception is already set */
+ return -1;
+ }
- return Py_BuildValue("i", sr_java_thread_cmp(this->thread, cmp_to->thread));
+ return normalize_cmp(sr_java_thread_cmp(self->thread, other->thread));
}
PyObject *
diff --git a/python/py_java_thread.h b/python/py_java_thread.h
index a0754c5..f9958f6 100644
--- a/python/py_java_thread.h
+++ b/python/py_java_thread.h
@@ -57,9 +57,11 @@ 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_cmp(PyObject *self, PyObject *args);
PyObject *sr_py_java_thread_quality_counts(PyObject *self, PyObject *args);
PyObject *sr_py_java_thread_quality(PyObject *self, PyObject *args);
PyObject *sr_py_java_thread_format_funs(PyObject *self, PyObject *args);
diff --git a/python/py_koops_frame.c b/python/py_koops_frame.c
index 778af3f..a7fc9b7 100644
--- a/python/py_koops_frame.c
+++ b/python/py_koops_frame.c
@@ -37,20 +37,12 @@
"Clones the frame object. All new structures are independent " \
"on the original object."
-#define f_cmp_doc "Usage: frame.cmp(frame2)\n" \
- "frame2: satyr.KerneloopsFrame - another frame to compare\n" \
- "Returns: integer - distance\n" \
- "Compares frame to frame2. Returns 0 if frame = frame2, " \
- "<0 if frame is 'less' than frame2, >0 if frame is 'more' " \
- "than frame2."
-
static PyMethodDef
frame_methods[] =
{
/* methods */
{ "dup", sr_py_koops_frame_dup, METH_NOARGS, f_dup_doc },
- { "cmp", sr_py_koops_frame_cmp, METH_VARARGS, f_cmp_doc },
{ NULL },
};
@@ -101,7 +93,7 @@ sr_py_koops_frame_type =
NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
- NULL, /* tp_compare */
+ sr_py_koops_frame_cmp, /* tp_compare */
NULL, /* tp_repr */
NULL, /* tp_as_number */
NULL, /* tp_as_sequence */
@@ -237,19 +229,11 @@ sr_py_koops_frame_dup(PyObject *self, PyObject *args)
return (PyObject*)fo;
}
-PyObject *
-sr_py_koops_frame_cmp(PyObject *self, PyObject *args)
+int
+sr_py_koops_frame_cmp(PyObject *self, PyObject *other)
{
- PyObject *compare_to;
- if (!PyArg_ParseTuple(args,
- "O!",
- &sr_py_koops_frame_type,
- &compare_to))
- {
- return NULL;
- }
-
struct sr_koops_frame *f1 = ((struct sr_py_koops_frame*)self)->frame;
- struct sr_koops_frame *f2 = ((struct sr_py_koops_frame*)compare_to)->frame;
- return Py_BuildValue("i", sr_koops_frame_cmp(f1, f2));
+ struct sr_koops_frame *f2 = ((struct sr_py_koops_frame*)other)->frame;
+
+ return normalize_cmp(sr_koops_frame_cmp(f1, f2));
}
diff --git a/python/py_koops_frame.h b/python/py_koops_frame.h
index e9c13f5..ecbf874 100644
--- a/python/py_koops_frame.h
+++ b/python/py_koops_frame.h
@@ -56,9 +56,13 @@ void sr_py_koops_frame_free(PyObject *object);
*/
PyObject *sr_py_koops_frame_str(PyObject *self);
+/*
+ * cmp
+ */
+int sr_py_koops_frame_cmp(PyObject *self, PyObject *other);
+
/* methods */
PyObject *sr_py_koops_frame_dup(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_cmp(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
diff --git a/python/py_python_frame.c b/python/py_python_frame.c
index 9e5e5c6..e654b64 100644
--- a/python/py_python_frame.c
+++ b/python/py_python_frame.c
@@ -34,20 +34,12 @@
"Clones the frame object. All new structures are independent " \
"on the original object."
-#define f_cmp_doc "Usage: frame.cmp(frame2)\n" \
- "frame2: satyr.Frame - another frame to compare\n" \
- "Returns: integer - distance\n" \
- "Compares frame to frame2. Returns 0 if frame = frame2, " \
- "<0 if frame is 'less' than frame2, >0 if frame is 'more' " \
- "than frame2."
-
static PyMethodDef
frame_methods[] =
{
/* methods */
{ "dup", sr_py_python_frame_dup, METH_NOARGS, f_dup_doc },
- { "cmp", sr_py_python_frame_cmp, METH_VARARGS, f_cmp_doc },
{ NULL },
};
@@ -86,7 +78,7 @@ sr_py_python_frame_type =
NULL, /* tp_print */
NULL, /* tp_getattr */
NULL, /* tp_setattr */
- NULL, /* tp_compare */
+ sr_py_python_frame_cmp, /* tp_compare */
NULL, /* tp_repr */
NULL, /* tp_as_number */
NULL, /* tp_as_sequence */
@@ -211,19 +203,11 @@ sr_py_python_frame_dup(PyObject *self, PyObject *args)
return (PyObject*)fo;
}
-PyObject *
-sr_py_python_frame_cmp(PyObject *self, PyObject *args)
+int
+sr_py_python_frame_cmp(PyObject *self, PyObject *other)
{
- PyObject *compare_to;
- if (!PyArg_ParseTuple(args,
- "O!",
- &sr_py_python_frame_type,
- &compare_to))
- {
- return NULL;
- }
-
struct sr_python_frame *f1 = ((struct sr_py_python_frame*)self)->frame;
- struct sr_python_frame *f2 = ((struct sr_py_python_frame*)compare_to)->frame;
- return Py_BuildValue("i", sr_python_frame_cmp(f1, f2));
+ struct sr_python_frame *f2 = ((struct sr_py_python_frame*)other)->frame;
+
+ return normalize_cmp(sr_python_frame_cmp(f1, f2));
}
diff --git a/python/py_python_frame.h b/python/py_python_frame.h
index f0848c2..736056b 100644
--- a/python/py_python_frame.h
+++ b/python/py_python_frame.h
@@ -56,9 +56,13 @@ void sr_py_python_frame_free(PyObject *object);
*/
PyObject *sr_py_python_frame_str(PyObject *self);
+/**
+ * cmp
+ */
+int sr_py_python_frame_cmp(PyObject *self, PyObject *other);
+
/* methods */
PyObject *sr_py_python_frame_dup(PyObject *self, PyObject *args);
-PyObject *sr_py_python_frame_cmp(PyObject *self, PyObject *args);
#ifdef __cplusplus
}
diff --git a/tests/python/gdb.py b/tests/python/gdb.py
index 54f0fbf..ea04776 100755
--- a/tests/python/gdb.py
+++ b/tests/python/gdb.py
@@ -35,11 +35,13 @@ class TestGdbStacktrace(BindingsTestCase):
def test_dup(self):
dup = self.trace.dup()
- self.assertNotEqual(dup.threads, self.trace.threads)
+ self.assertNotEqual(id(dup.threads), id(self.trace.threads))
+ self.assertEqual(dup.threads, self.trace.threads)
dup.threads = dup.threads[:5]
dup2 = dup.dup()
- self.assertEqual(len(dup.threads), len(dup2.threads))
+ self.assertNotEqual(id(dup.threads), id(dup2.threads))
+ self.assertEqual(dup.threads, dup2.threads)
def test_prepare_linked_list(self):
dup = self.trace.dup()
@@ -63,6 +65,13 @@ class TestGdbThread(BindingsTestCase):
def test_getset(self):
self.assertGetSetCorrect(self.thread, 'number', 2, 9000)
+ def test_cmp(self):
+ self.assertEqual(self.thread, self.thread)
+ dup = self.thread.dup()
+ self.assertEqual(self.thread, dup)
+ dup.number = 9000
+ self.assertNotEqual(self.thread, dup)
+
class TestGdbSharedlib(BindingsTestCase):
def setUp(self):
self.shlib = satyr.GdbStacktrace(contents).libs[0]
@@ -94,11 +103,10 @@ class TestGdbFrame(BindingsTestCase):
def test_cmp(self):
dup = self.frame.dup()
- self.assertEqual(dup.cmp(dup, 0), 0)
- self.assertEqual(dup.cmp(self.frame, 0), 0)
- self.assertEqual(dup.cmp(self.frame, 0), 0)
+ self.assertEqual(dup, dup)
+ self.assertEqual(dup, self.frame)
dup.function_name = 'another'
- self.assertNotEqual(dup.cmp(self.frame, 0), 0)
+ self.assertNotEqual(dup, self.frame)
def test_getset(self):
self.assertGetSetCorrect(self.frame, 'function_name', 'write', 'foo bar')
diff --git a/tests/python/java.py b/tests/python/java.py
index 37bf286..ba0cb49 100755
--- a/tests/python/java.py
+++ b/tests/python/java.py
@@ -34,11 +34,13 @@ class TestJavaStacktrace(BindingsTestCase):
def test_dup(self):
dup = self.trace.dup()
- self.assertNotEqual(dup.threads, self.trace.threads)
+ self.assertNotEqual(id(dup.threads), id(self.trace.threads))
+ self.assertEqual(dup.threads, self.trace.threads)
dup.threads = dup.threads[:5]
dup2 = dup.dup()
self.assertEqual(len(dup.threads), len(dup2.threads))
+ self.assertNotEqual(id(dup.threads), id(dup2.threads))
def test_prepare_linked_list(self):
dup = self.trace.dup()
@@ -57,6 +59,13 @@ class TestJavaThread(BindingsTestCase):
def test_getset(self):
self.assertGetSetCorrect(self.thread, 'name', None, 'elvis')
+ def test_cmp(self):
+ self.assertEqual(self.thread, self.thread)
+ dup = self.thread.dup()
+ self.assertEqual(self.thread, dup)
+ dup.name = ' 45678987\n\n\n\n'
+ self.assertNotEqual(self.thread, dup)
+
class TestJavaSharedlib(BindingsTestCase):
def setUp(self):
self.shlib = satyr.JavaStacktrace(contents).libs[0]
@@ -82,11 +91,14 @@ class TestJavaFrame(BindingsTestCase):
def test_cmp(self):
dup = self.frame.dup()
- self.assertEqual(dup.cmp(dup), 0)
- self.assertEqual(dup.cmp(self.frame), 0)
- self.assertEqual(dup.cmp(self.frame), 0)
+ self.assertEqual(dup, dup)
+ self.assertEqual(dup, self.frame)
+ self.assertEqual(dup, self.frame)
+ self.assertNotEqual(id(dup), id(self.frame))
dup.name = 'another'
- self.assertNotEqual(dup.cmp(self.frame), 0)
+ self.assertNotEqual(dup, self.frame)
+ self.assertFalse(dup > self.frame)
+ self.assertTrue(dup < self.frame)
def test_getset(self):
self.assertGetSetCorrect(self.frame, 'name', 'org.hibernate.exception.ConstraintViolationException', 'long.name.is.Long')
diff --git a/tests/python/koops.py b/tests/python/koops.py
index fbeb8dd..df6462f 100755
--- a/tests/python/koops.py
+++ b/tests/python/koops.py
@@ -34,11 +34,13 @@ class TestKerneloops(BindingsTestCase):
def test_dup(self):
dup = self.koops.dup()
- self.assertNotEqual(dup.frames, self.koops.frames)
+ self.assertNotEqual(id(dup.frames), id(self.koops.frames))
+ self.assertEqual(dup.frames, self.koops.frames)
dup.frames = dup.frames[:5]
dup2 = dup.dup()
self.assertEqual(len(dup.frames), len(dup2.frames))
+ self.assertNotEqual(id(dup.frames), id(dup2.frames))
def test_normalize(self):
dup = self.koops.dup()
@@ -72,11 +74,15 @@ class TestKoopsFrame(BindingsTestCase):
def test_cmp(self):
dup = self.frame.dup()
- self.assertEqual(dup.cmp(dup), 0)
- self.assertEqual(dup.cmp(self.frame), 0)
- self.assertEqual(dup.cmp(self.frame), 0)
+ self.assertEqual(dup, dup)
+ self.assertEqual(dup, self.frame)
+ self.assertEqual(dup, self.frame)
+ self.assertNotEqual(id(dup), id(self.frame))
+
dup.reliable = False
- self.assertNotEqual(dup.cmp(self.frame), 0)
+ self.assertNotEqual(dup, self.frame)
+ self.assertTrue(dup > self.frame)
+ self.assertFalse(dup < self.frame)
def test_getset(self):
self.assertGetSetCorrect(self.frame, 'reliable', True, False)
diff --git a/tests/python/python.py b/tests/python/python.py
index 59d61ce..5b8b32f 100755
--- a/tests/python/python.py
+++ b/tests/python/python.py
@@ -31,11 +31,13 @@ class TestPythonStacktrace(BindingsTestCase):
def test_dup(self):
dup = self.trace.dup()
- self.assertNotEqual(dup.frames, self.trace.frames)
+ self.assertNotEqual(id(dup.frames), id(self.trace.frames))
+ self.assertEqual(dup.frames, self.trace.frames)
dup.frames = dup.frames[:5]
dup2 = dup.dup()
self.assertEqual(len(dup.frames), len(dup2.frames))
+ self.assertNotEqual(id(dup.frames), id(dup2.frames))
def test_prepare_linked_list(self):
dup = self.trace.dup()
@@ -73,11 +75,13 @@ class TestPythonFrame(BindingsTestCase):
def test_cmp(self):
dup = self.frame.dup()
- self.assertEqual(dup.cmp(dup), 0)
- self.assertEqual(dup.cmp(self.frame), 0)
- self.assertEqual(dup.cmp(self.frame), 0)
+ self.assertEqual(dup, dup)
+ self.assertEqual(dup, self.frame)
+ self.assertEqual(dup, self.frame)
+ self.assertNotEqual(id(dup), id(self.frame))
dup.function_name = 'another'
- self.assertNotEqual(dup.cmp(self.frame), 0)
+ self.assertNotEqual(dup, self.frame)
+ self.assertTrue(dup > self.frame)
def test_getset(self):
self.assertGetSetCorrect(self.frame, 'file_name', '/usr/share/PackageKit/helpers/yum/yumBackend.py', 'java.py')
--
1.7.11.7
10 years, 12 months
[ABRT PATCH] fixed race in the console notification closes #643
by Jiri Moskovcak
Signed-off-by: Jiri Moskovcak <jmoskovc(a)redhat.com>
---
src/cli/abrt-console-notification.sh | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/src/cli/abrt-console-notification.sh b/src/cli/abrt-console-notification.sh
index d1defc8..6be1620 100755
--- a/src/cli/abrt-console-notification.sh
+++ b/src/cli/abrt-console-notification.sh
@@ -1,13 +1,16 @@
#! /bin/sh
-LPATH="$HOME/.cache/abrt/lastnotificaion"
+LPATHDIR="$HOME/.cache/abrt/"
+SINCEFILE="lastnotificaion"
+TMPPATH=`mktemp --tmpdir="$LPATHDIR"`
SINCE=0
if [ -f $LPATH ]; then
- SINCE=`cat $LPATH`
+ SINCE=`cat $LPATHDIR$SINCEFILE`
fi
# always update the lastnotification
-date +%s > "$LPATH"
+date +%s > "$TMPPATH"
+mv "$TMPPATH" "$LPATHDIR$SINCEFILE"
abrt-cli status --since="$SINCE"
--
1.8.1.4
10 years, 12 months
[SATYR PATCH] python: get rid of explicit getters and setters
by Martin Milata
This commit does three slightly different things:
1. It replaces most of the explicit get_ and set_ methods in the Python
API with (computed) attribute access [1], making it slightly less
cumbersome to use.
2. In the python bindings, the getters and setters that had to be
defined for each attribute as two functions have been replaced with
generic versions that need to be written only once for each member
type.
The generic [gs]etters access the members using their structure
offsets. Preprocessor macros are provided to compute the offsets.
Such approach is generally somewhat unsafe as it bypasses the type
system - as a compensation, test cases are present which check that
access to all the attributes works correctly.
3. The SYMS_{OK,WRONG,NOT_FOUND} constants were moved from the
GdbSharedlib class to the module level.
Related to #59 and #69.
[1] http://docs.python.org/2.7/c-api/typeobj.html#PyTypeObject.tp_getset
Signed-off-by: Martin Milata <mmilata(a)redhat.com>
---
python/Makefile.am | 2 +
python/py_common.c | 133 +++++++++++++++
python/py_common.h | 101 ++++++++++++
python/py_gdb_frame.c | 312 ++++++++---------------------------
python/py_gdb_frame.h | 18 ---
python/py_gdb_sharedlib.c | 155 +++++-------------
python/py_gdb_sharedlib.h | 13 +-
python/py_gdb_thread.c | 57 +++----
python/py_gdb_thread.h | 4 -
python/py_java_frame.c | 248 +++++-----------------------
python/py_java_frame.h | 16 --
python/py_java_thread.c | 50 +++---
python/py_java_thread.h | 4 -
python/py_koops_frame.c | 366 ++++++------------------------------------
python/py_koops_frame.h | 25 ---
python/py_koops_stacktrace.c | 23 ++-
python/py_koops_stacktrace.h | 3 +-
python/py_module.c | 6 +
python/py_python_frame.c | 184 ++++-----------------
python/py_python_frame.h | 12 --
python/py_python_stacktrace.c | 120 +++-----------
python/py_python_stacktrace.h | 9 --
tests/python/gdb.py | 43 +++--
tests/python/java.py | 36 +++--
tests/python/koops.py | 35 ++--
tests/python/python.py | 30 +++-
tests/python/test_helpers.py | 14 ++
27 files changed, 672 insertions(+), 1347 deletions(-)
create mode 100644 python/py_common.c
create mode 100644 python/py_common.h
create mode 100644 tests/python/test_helpers.py
diff --git a/python/Makefile.am b/python/Makefile.am
index d72012a..a710e18 100644
--- a/python/Makefile.am
+++ b/python/Makefile.am
@@ -32,6 +32,8 @@ _satyr_la_SOURCES = \
py_java_stacktrace.c \
py_metrics.h \
py_metrics.c \
+ py_common.h \
+ py_common.c \
py_module.c
_satyr_la_CPPFLAGS = \
diff --git a/python/py_common.c b/python/py_common.c
new file mode 100644
index 0000000..245b58b
--- /dev/null
+++ b/python/py_common.c
@@ -0,0 +1,133 @@
+/*
+ py_common.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 "lib/utils.h"
+
+/*
+ * Generic getters/setters that accept a struct getset_offsets as the data
+ * argument.
+ */
+
+PyObject *
+sr_py_getter_string(PyObject *self, void *data)
+{
+ struct getset_offsets *gsoff = data;
+ char *str = MEMB_T(char*, MEMB(self, gsoff->c_struct_offset), gsoff->member_offset);
+
+ if (str == NULL)
+ Py_RETURN_NONE;
+
+ return PyString_FromString(str);
+}
+
+int
+sr_py_setter_string(PyObject *self, PyObject *rhs, void *data)
+{
+ struct getset_offsets *gsoff = data;
+
+ char *newvalue = PyString_AsString(rhs);
+ if (!newvalue)
+ return -1;
+
+ char *str = MEMB_T(char*, MEMB(self, gsoff->c_struct_offset), gsoff->member_offset);
+ free(str);
+ MEMB_T(char*, MEMB(self, gsoff->c_struct_offset), gsoff->member_offset) = sr_strdup(newvalue);
+
+ return 0;
+}
+
+PyObject *
+sr_py_getter_uint32(PyObject *self, void *data)
+{
+ struct getset_offsets *gsoff = data;
+ uint32_t num = MEMB_T(uint32_t, MEMB(self, gsoff->c_struct_offset), gsoff->member_offset);
+ return PyInt_FromLong(num);
+}
+
+int
+sr_py_setter_uint32(PyObject *self, PyObject *rhs, void *data)
+{
+ struct getset_offsets *gsoff = data;
+
+ long newvalue = PyInt_AsLong(rhs);
+ if (PyErr_Occurred())
+ return -1;
+
+ if (newvalue < 0)
+ {
+ PyErr_SetString(PyExc_ValueError, "Value must not be negative.");
+ return -1;
+ }
+
+ MEMB_T(uint32_t, MEMB(self, gsoff->c_struct_offset), gsoff->member_offset)
+ = (uint32_t)newvalue;
+ return 0;
+}
+
+PyObject *
+sr_py_getter_bool(PyObject *self, void *data)
+{
+ struct getset_offsets *gsoff = data;
+
+ bool b = MEMB_T(bool, MEMB(self, gsoff->c_struct_offset), gsoff->member_offset);
+ return PyBool_FromLong(b);
+}
+
+int
+sr_py_setter_bool(PyObject *self, PyObject *rhs, void *data)
+{
+ struct getset_offsets *gsoff = data;
+
+ if (!PyBool_Check(rhs))
+ {
+ PyErr_SetString(PyExc_TypeError, "Boolean required.");
+ return -1;
+ }
+
+ bool newvalue = (rhs == Py_True);
+ MEMB_T(bool, MEMB(self, gsoff->c_struct_offset), gsoff->member_offset) = newvalue;
+
+ return 0;
+}
+
+PyObject *
+sr_py_getter_uint64(PyObject *self, void *data)
+{
+ struct getset_offsets *gsoff = data;
+
+ uint64_t num
+ = MEMB_T(uint64_t, MEMB(self, gsoff->c_struct_offset), gsoff->member_offset);
+ return PyLong_FromUnsignedLongLong(num);
+}
+
+int
+sr_py_setter_uint64(PyObject *self, PyObject *rhs, void *data)
+{
+ struct getset_offsets *gsoff = data;
+
+ unsigned long long newvalue = PyInt_AsUnsignedLongLongMask(rhs);
+ if (PyErr_Occurred())
+ return -1;
+
+ MEMB_T(uint64_t, MEMB(self, gsoff->c_struct_offset), gsoff->member_offset) = newvalue;
+ return 0;
+}
diff --git a/python/py_common.h b/python/py_common.h
new file mode 100644
index 0000000..c778cee
--- /dev/null
+++ b/python/py_common.h
@@ -0,0 +1,101 @@
+/*
+ py_common.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_COMMON_H
+#define SATYR_PY_COMMON_H
+
+/**
+ * @file
+ * @brief Common routines for python bindings.
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <Python.h>
+#include <structmember.h>
+
+/*
+ * Struct member access using offsets. The second variant is useful for nested
+ * structures.
+ *
+ * MEMB_T(type, offsetof(typeof(st), member)) == (type)(st->member)
+ * MEMB(st, offsetof(typeof(st), member)) == (void*)(st->member)
+ */
+#define MEMB_T(type, st, off) *(type *)((char*)st + off)
+#define MEMB(st, off) MEMB_T(void*, st, off)
+
+/*
+ * This struct is used for generic getters and setters. Most of satyr's python
+ * object structures contain pointer to a corresponding C structure, which in
+ * turn contains the members that are exposed in the python API.
+ *
+ * If we know the offset of the pointer to the C structure in the python object
+ * and the offset of the member in the C structure, we can access the member
+ * using generic (per-type) functions, declared further below.
+ */
+struct getset_offsets
+{
+ size_t c_struct_offset;
+ size_t member_offset;
+};
+
+/*
+ * These macros make it possible to initialize several struct getset_offsets
+ * without typing too much and entering the offsets by hand.
+ *
+ * You need to define GSOFF_PY_STRUCT to be the type of the structure defining
+ * the python object, GSOFF_PY_MEMBER to be the name of its member pointing to
+ * the C structure, and GSOFF_C_STRUCT to be the type of the C structure. Use
+ * GSOFF_MEMBER for each member you want to access, GSOFF_MEMBER(m) defines the
+ * variable gsoff_m which can be used in the declaration of getters and
+ * setters.
+ *
+ * See python/py_gdb_frame.c for example usage.
+ */
+#define GSOFF_START static struct getset_offsets
+#define GSOFF_MEMBER(c_member) \
+ gsoff_ ## c_member = { \
+ .c_struct_offset = offsetof(struct GSOFF_PY_STRUCT, GSOFF_PY_MEMBER), \
+ .member_offset = offsetof(struct GSOFF_C_STRUCT, c_member) \
+ }
+#define GSOFF_END ;
+
+/*
+ * Generic getters/setters that accept a struct getset_offsets as the data
+ * argument.
+ */
+PyObject *sr_py_getter_string(PyObject *self, void *data);
+int sr_py_setter_string(PyObject *self, PyObject *rhs, void *data);
+
+PyObject *sr_py_getter_uint32(PyObject *self, void *data);
+int sr_py_setter_uint32(PyObject *self, PyObject *rhs, void *data);
+
+PyObject *sr_py_getter_bool(PyObject *self, void *data);
+int sr_py_setter_bool(PyObject *self, PyObject *rhs, void *data);
+
+PyObject *sr_py_getter_uint64(PyObject *self, void *data);
+int sr_py_setter_uint64(PyObject *self, PyObject *rhs, void *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SATYR_PY_COMMON_H */
diff --git a/python/py_gdb_frame.c b/python/py_gdb_frame.c
index b69b1f6..36b7170 100644
--- a/python/py_gdb_frame.c
+++ b/python/py_gdb_frame.c
@@ -17,6 +17,7 @@
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_gdb_frame.h"
#include <inttypes.h>
@@ -31,53 +32,14 @@
"satyr.GdbFrame() - creates an empty frame\n" \
"satyr.GdbFrame(str) - parses str and fills the frame object"
-#define f_get_function_name_doc "Usage: frame.get_function_name()\n" \
- "Returns: string - function name"
-
-#define f_set_function_name_doc "Usage: frame.set_function_name(newname)\n" \
- "newname: string - new function name"
-
-#define f_get_function_type_doc "Usage: frame.get_function_type()\n" \
- "Returns: string - function type"
-
-#define f_set_function_type_doc "Usage: frame.set_function_type(newtype)\n" \
- "newtype: string - new function type"
-
-#define f_get_number_doc "Usage: frame.get_number()\n" \
- "Returns: positive integer - frame number"
-
-#define f_set_number_doc "Usage: frame.set_number(N)\n" \
- "N: positive integer - new frame number"
-
-#define f_get_source_line_doc "Usage: frame.get_source_line()\n" \
- "Returns: positive integer - source line number"
-
-#define f_set_source_line_doc "Usage: frame.set_source_line(N)\n" \
- "N: positive integer - new source line number"
-
-#define f_get_source_file_doc "Usage: frame.get_source_file()\n" \
- "Returns: string - source file name"
-
-#define f_set_source_file_doc "Usage: frame.set_source_file(newname)\n" \
- "newname: string - new source file name"
-
-#define f_get_signal_handler_called_doc "Usage: frame.get_signal_handler_called()\n" \
- "Returns: integer - 0 = False, 1 = True"
-
-#define f_set_signal_handler_called_doc "Usage: frame.set_signal_handler_called(N)\n" \
- "N: integer - 0 = False, anything else = True"
-
-#define f_get_address_doc "Usage: frame.get_address()\n" \
- "Returns: positive long integer - address"
-
-#define f_set_address_doc "Usage: frame.set_address(N)\n" \
- "N: positive long integer - new address"
-
-#define f_get_library_name_doc "Usage: frame.get_library_name()\n" \
- "Returns: string - library name"
-
-#define f_set_library_name_doc "Usage: frame.set_library_name(newname)\n" \
- "newname: string - new library name"
+#define f_function_name_doc "Function name (string)"
+#define f_function_type_doc "Function type (string)"
+#define f_number_doc "Frame number (positive integer)"
+#define f_source_file_doc "Source file name (string)"
+#define f_source_line_doc "Source line number (positive integer)"
+#define f_signal_handler_called_doc "True if the frame is signal handler (bool)"
+#define f_address_doc "Address of the current instruction (long)"
+#define f_library_name_doc "Executable file name (string)"
#define f_dup_doc "Usage: frame.dup()\n" \
"Returns: satyr.GdbFrame - a new clone of frame\n" \
@@ -109,28 +71,66 @@
static PyMethodDef
frame_methods[] =
{
- /* getters & setters */
- { "get_function_name", sr_py_gdb_frame_get_function_name, METH_NOARGS, f_get_function_name_doc },
- { "set_function_name", sr_py_gdb_frame_set_function_name, METH_VARARGS, f_set_function_name_doc },
- { "get_function_type", sr_py_gdb_frame_get_function_type, METH_NOARGS, f_get_function_type_doc },
- { "set_function_type", sr_py_gdb_frame_set_function_type, METH_VARARGS, f_set_function_type_doc },
- { "get_number", sr_py_gdb_frame_get_number, METH_NOARGS, f_get_number_doc },
- { "set_number", sr_py_gdb_frame_set_number, METH_VARARGS, f_set_number_doc },
- { "get_source_file", sr_py_gdb_frame_get_source_file, METH_NOARGS, f_get_source_file_doc },
- { "set_source_file", sr_py_gdb_frame_set_source_file, METH_VARARGS, f_set_source_file_doc },
- { "get_source_line", sr_py_gdb_frame_get_source_line, METH_NOARGS, f_get_source_line_doc },
- { "set_source_line", sr_py_gdb_frame_set_source_line, METH_VARARGS, f_set_source_line_doc },
- { "get_signal_handler_called", sr_py_gdb_frame_get_signal_handler_called, METH_NOARGS, f_get_signal_handler_called_doc },
- { "set_signal_handler_called", sr_py_gdb_frame_set_signal_handler_called, METH_VARARGS, f_set_signal_handler_called_doc },
- { "get_address", sr_py_gdb_frame_get_address, METH_NOARGS, f_get_address_doc },
- { "set_address", sr_py_gdb_frame_set_address, METH_VARARGS, f_set_address_doc },
- { "get_library_name", sr_py_gdb_frame_get_library_name, METH_NOARGS, f_get_library_name_doc },
- { "set_library_name", sr_py_gdb_frame_set_library_name, METH_VARARGS, f_set_library_name_doc },
/* methods */
- { "dup", sr_py_gdb_frame_dup, METH_NOARGS, f_dup_doc },
- { "cmp", sr_py_gdb_frame_cmp, METH_VARARGS, f_cmp_doc },
- { "calls_func", sr_py_gdb_frame_calls_func, METH_VARARGS, f_calls_func_doc },
- { "calls_func_in_file", sr_py_gdb_frame_calls_func_in_file, METH_VARARGS, f_calls_func_in_file_doc },
+ { "dup", sr_py_gdb_frame_dup, METH_NOARGS, f_dup_doc },
+ { "cmp", sr_py_gdb_frame_cmp, METH_VARARGS, f_cmp_doc },
+ { "calls_func", sr_py_gdb_frame_calls_func, METH_VARARGS, f_calls_func_doc },
+ { "calls_func_in_file", sr_py_gdb_frame_calls_func_in_file, METH_VARARGS, f_calls_func_in_file_doc },
+ { NULL },
+};
+
+/*
+ * This sequence of #defines and macros expands to definition of struct
+ * getset_offsets, one for each member to be accessed with the generic
+ * getters/setters.
+ *
+ * Python objects for GDB frames store data in struct sr_py_gdb_frame, which
+ * contains pointer named frame that points to the GDB frame C structure named
+ * struct sr_gdb_frame. Most of the satyr python object follow similar scheme,
+ * which allows us to use generic getters/setters that only need to know two
+ * offsets.
+ */
+
+/* GSOFF_PY_STRUCT must be defined to the type of the python object structure (without struct keyword). */
+#define GSOFF_PY_STRUCT sr_py_gdb_frame
+
+/* GSOFF_PY_MEMBER must be defined to name of GSOFF_PY_STRUCT's member that points to the satyr C structure. */
+#define GSOFF_PY_MEMBER frame
+
+/* GSOFF_C_STRUCT must be defined to the type of the C structure (without struct keyword) */
+#define GSOFF_C_STRUCT sr_gdb_frame
+
+/*
+ * Individual GSOFF_MEMBER invocations need to be surrounded by GSOFF_START and
+ * GSOFF_END and need to be separated by commas (which must not be after the
+ * last invocation). The order does not matter.
+ *
+ * E.g. the GSOFF_MEMBER(function_name) expands to definition of global
+ * variable gsoff_function_name containing the right offsets, which is then
+ * used int the frame_getset[] definition below.
+ */
+GSOFF_START
+GSOFF_MEMBER(function_name),
+GSOFF_MEMBER(function_type),
+GSOFF_MEMBER(source_file),
+GSOFF_MEMBER(number),
+GSOFF_MEMBER(source_line),
+GSOFF_MEMBER(signal_handler_called),
+GSOFF_MEMBER(address),
+GSOFF_MEMBER(library_name)
+GSOFF_END
+
+static PyGetSetDef
+frame_getset[] =
+{
+ { (char*)"function_name", sr_py_getter_string, sr_py_setter_string, (char*)f_function_name_doc, &gsoff_function_name },
+ { (char*)"function_type", sr_py_getter_string, sr_py_setter_string, (char*)f_function_type_doc, &gsoff_function_type },
+ { (char*)"number", sr_py_getter_uint32, sr_py_setter_uint32, (char*)f_number_doc, &gsoff_number },
+ { (char*)"source_file", sr_py_getter_string, sr_py_setter_string, (char*)f_source_file_doc, &gsoff_source_file },
+ { (char*)"source_line", sr_py_getter_uint32, sr_py_setter_uint32, (char*)f_source_line_doc, &gsoff_source_line },
+ { (char*)"signal_handler_called", sr_py_getter_bool, sr_py_setter_bool, (char*)f_signal_handler_called_doc, &gsoff_signal_handler_called },
+ { (char*)"address", sr_py_getter_uint64, sr_py_setter_uint64, (char*)f_address_doc, &gsoff_address },
+ { (char*)"library_name", sr_py_getter_string, sr_py_setter_string, (char*)f_library_name_doc, &gsoff_library_name },
{ NULL },
};
@@ -165,9 +165,9 @@ sr_py_gdb_frame_type =
0, /* tp_weaklistoffset */
NULL, /* tp_iter */
NULL, /* tp_iternext */
- frame_methods, /* tp_methods */
+ frame_methods, /* tp_methods */
NULL, /* tp_members */
- NULL, /* tp_getset */
+ frame_getset, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
@@ -249,178 +249,6 @@ sr_py_gdb_frame_str(PyObject *self)
return result;
}
-/* getters & setters */
-
-/* function_name */
-PyObject *
-sr_py_gdb_frame_get_function_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_gdb_frame*)self)->frame->function_name);
-}
-
-PyObject *
-sr_py_gdb_frame_set_function_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_gdb_frame *frame = ((struct sr_py_gdb_frame*)self)->frame;
- free(frame->function_name);
- frame->function_name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* function_type */
-PyObject *
-sr_py_gdb_frame_get_function_type(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_gdb_frame*)self)->frame->function_type);
-}
-
-PyObject *
-sr_py_gdb_frame_set_function_type(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_gdb_frame *frame = ((struct sr_py_gdb_frame*)self)->frame;
- free(frame->function_type);
- frame->function_type = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* number */
-PyObject *
-sr_py_gdb_frame_get_number(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("i", ((struct sr_py_gdb_frame*)self)->frame->number);
-}
-
-PyObject *
-sr_py_gdb_frame_set_number(PyObject *self, PyObject *args)
-{
- int newvalue;
- if (!PyArg_ParseTuple(args, "i", &newvalue))
- return NULL;
-
- if (newvalue < 0)
- {
- PyErr_SetString(PyExc_ValueError, "Frame number must not be negative.");
- return NULL;
- }
-
- struct sr_gdb_frame *frame = ((struct sr_py_gdb_frame*)self)->frame;
- frame->number = newvalue;
- Py_RETURN_NONE;
-}
-
-/* source_file */
-PyObject *
-sr_py_gdb_frame_get_source_file(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_gdb_frame*)self)->frame->source_file);
-}
-
-PyObject *
-sr_py_gdb_frame_set_source_file(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_gdb_frame *frame = ((struct sr_py_gdb_frame*)self)->frame;
- free(frame->source_file);
- frame->source_file = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* source_line */
-PyObject *
-sr_py_gdb_frame_get_source_line(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("i", ((struct sr_py_gdb_frame*)self)->frame->source_line);
-}
-
-PyObject *
-sr_py_gdb_frame_set_source_line(PyObject *self, PyObject *args)
-{
- int newvalue;
- if (!PyArg_ParseTuple(args, "i", &newvalue))
- return NULL;
-
- if (newvalue < 0)
- {
- PyErr_SetString(PyExc_ValueError, "Source line must not be negative.");
- return NULL;
- }
-
- struct sr_gdb_frame *frame = ((struct sr_py_gdb_frame*)self)->frame;
- frame->source_line = newvalue;
- Py_RETURN_NONE;
-}
-
-/* signal_handler_called */
-PyObject *
-sr_py_gdb_frame_get_signal_handler_called(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("i", ((struct sr_py_gdb_frame*)self)->frame->signal_handler_called);
-}
-
-PyObject *
-sr_py_gdb_frame_set_signal_handler_called(PyObject *self, PyObject *args)
-{
- int newvalue;
- if (!PyArg_ParseTuple(args, "i", &newvalue))
- return NULL;
-
- struct sr_gdb_frame *frame = ((struct sr_py_gdb_frame*)self)->frame;
- frame->signal_handler_called = newvalue ? 1 : 0;
- Py_RETURN_NONE;
-}
-
-/* address */
-PyObject *
-sr_py_gdb_frame_get_address(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("K",
- (unsigned long long)(((struct sr_py_gdb_frame*)self)->frame->address));
-}
-
-PyObject *
-sr_py_gdb_frame_set_address(PyObject *self, PyObject *args)
-{
- unsigned long long newvalue;
- if (!PyArg_ParseTuple(args, "K", &newvalue))
- return NULL;
-
- struct sr_gdb_frame *frame = ((struct sr_py_gdb_frame*)self)->frame;
- frame->address = newvalue;
- Py_RETURN_NONE;
-}
-
-/* library_name */
-PyObject *
-sr_py_gdb_frame_get_library_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_gdb_frame*)self)->frame->library_name);
-}
-
-PyObject *
-sr_py_gdb_frame_set_library_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_gdb_frame *frame = ((struct sr_py_gdb_frame*)self)->frame;
- free(frame->library_name);
- frame->library_name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-
/* methods */
PyObject *
sr_py_gdb_frame_dup(PyObject *self, PyObject *args)
diff --git a/python/py_gdb_frame.h b/python/py_gdb_frame.h
index 8cf5691..4926014 100644
--- a/python/py_gdb_frame.h
+++ b/python/py_gdb_frame.h
@@ -56,24 +56,6 @@ void sr_py_gdb_frame_free(PyObject *object);
*/
PyObject *sr_py_gdb_frame_str(PyObject *self);
-/* getters & setters */
-PyObject *sr_py_gdb_frame_get_function_name(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_set_function_name(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_get_function_type(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_set_function_type(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_get_number(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_set_number(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_get_source_file(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_set_source_file(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_get_source_line(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_set_source_line(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_get_signal_handler_called(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_set_signal_handler_called(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_get_address(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_set_address(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_get_library_name(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_frame_set_library_name(PyObject *self, PyObject *args);
-
/* methods */
PyObject *sr_py_gdb_frame_dup(PyObject *self, PyObject *args);
PyObject *sr_py_gdb_frame_cmp(PyObject *self, PyObject *args);
diff --git a/python/py_gdb_sharedlib.c b/python/py_gdb_sharedlib.c
index 4737884..ed502f5 100644
--- a/python/py_gdb_sharedlib.c
+++ b/python/py_gdb_sharedlib.c
@@ -1,61 +1,35 @@
+#include "py_common.h"
#include "py_gdb_sharedlib.h"
#include "lib/gdb_sharedlib.h"
#include "lib/utils.h"
#define sharedlib_doc "satyr.GdbSharedlib - class representing a shared library loaded at the moment of crash"
-#define s_get_from_doc "Usage: sharedlib.get_from()\n" \
- "Returns: long - address where lib's memory begins"
-
-#define s_set_from_doc "Usage: sharedlib.set_from(newvalue)\n" \
- "Newvalue: long - address where lib's memory begins"
-
-#define s_get_to_doc "Usage: sharedlib.get_to()\n" \
- "Returns: long - address where lib's memory ends"
-
-#define s_set_to_doc "Usage: sharedlib.set_to(newvalue)\n" \
- "Newvalue: long - address where lib's memory ends"
-
-#define s_get_symbols_doc "Usage: sharedlib.get_symbols()\n" \
- "Returns: SYMS_OK / SYMS_NOT_FOUND / SYMS_WRONG"
-
-#define s_set_symbols_doc "Usage: sharedlib.set_symbols(newvalue)\n" \
- "Newvalue: SYMS_OK / SYMS_NOT_FOUND / SYMS_WRONG"
-
-#define s_get_soname_doc "Usage: sharedlib.get_soname()\n" \
- "Returns: string - library filename"
-
-#define s_set_soname_doc "Usage: sharedlib.set_soname(newvalue)\n" \
- "Newvalue: string - library filename"
-
-#define s_syms_ok_doc (char *)"Constant. Debug symbols for the library were loaded successfully."
-
-#define s_syms_wrong_doc (char *)"Constant. Debug symbols for the library were present, but did not match."
-
-#define s_syms_not_found_doc (char *)"Constant. Debug symbols for the library were not found."
-
-static PyMethodDef
-gdb_sharedlib_methods[] =
+#define s_from_doc "Address where lib's memory begins (long)"
+#define s_to_doc "Address where lib's memory ends (long)"
+#define s_symbols_doc "Symbol state (satyr.SYMS_OK / satyr.SYMS_NOT_FOUND / satyr.SYMS_WRONG)\n" \
+ "SYMS_OK: Debug symbols for the library were loaded successfully.\n" \
+ "SYMS_WRONG: Debug symbols for the library were present, but did not match.\n" \
+ "SYMS_NOT_FOUND: Debug symbols for the library were not found."
+#define s_soname_doc "Library file name (string)"
+
+/* See python/py_common.h and python/py_gdb_frame.c for generic getters/setters documentation. */
+#define GSOFF_PY_STRUCT sr_py_gdb_sharedlib
+#define GSOFF_PY_MEMBER sharedlib
+#define GSOFF_C_STRUCT sr_gdb_sharedlib
+GSOFF_START
+GSOFF_MEMBER(from),
+GSOFF_MEMBER(to),
+GSOFF_MEMBER(soname)
+GSOFF_END
+
+static PyGetSetDef
+gdb_sharedlib_getset[] =
{
- /* getters & setters */
- { "get_from", sr_py_gdb_sharedlib_get_from, METH_NOARGS, s_get_from_doc },
- { "set_from", sr_py_gdb_sharedlib_set_from, METH_VARARGS, s_set_from_doc },
- { "get_to", sr_py_gdb_sharedlib_get_to, METH_NOARGS, s_get_to_doc },
- { "set_to", sr_py_gdb_sharedlib_set_to, METH_VARARGS, s_set_to_doc },
- { "get_symbols", sr_py_gdb_sharedlib_get_symbols, METH_NOARGS, s_get_symbols_doc },
- { "set_symbols", sr_py_gdb_sharedlib_set_symbols, METH_VARARGS, s_set_symbols_doc },
- { "get_soname", sr_py_gdb_sharedlib_get_soname, METH_NOARGS, s_get_soname_doc },
- { "set_soname", sr_py_gdb_sharedlib_set_soname, METH_VARARGS, s_set_soname_doc },
- /* methods */
- { NULL },
-};
-
-static PyMemberDef
-gdb_sharedlib_members[] =
-{
- { (char *)"SYMS_OK", T_INT, offsetof(struct sr_py_gdb_sharedlib, syms_ok), READONLY, s_syms_ok_doc },
- { (char *)"SYMS_WRONG", T_INT, offsetof(struct sr_py_gdb_sharedlib, syms_wrong), READONLY, s_syms_wrong_doc },
- { (char *)"SYMS_NOT_FOUND", T_INT, offsetof(struct sr_py_gdb_sharedlib, syms_not_found), READONLY, s_syms_not_found_doc },
+ { (char*)"start_address", sr_py_getter_uint64, sr_py_setter_uint64, (char*)s_from_doc, &gsoff_from },
+ { (char*)"end_address", sr_py_getter_uint64, sr_py_setter_uint64, (char*)s_to_doc, &gsoff_to },
+ { (char*)"symbols", sr_py_gdb_sharedlib_get_symbols, sr_py_gdb_sharedlib_set_symbols, (char*)s_symbols_doc, NULL },
+ { (char*)"soname", sr_py_getter_string, sr_py_setter_string, (char*)s_soname_doc, &gsoff_soname },
{ NULL },
};
@@ -90,9 +64,9 @@ sr_py_gdb_sharedlib_type =
0, /* tp_weaklistoffset */
NULL, /* tp_iter */
NULL, /* tp_iternext */
- gdb_sharedlib_methods, /* tp_methods */
- gdb_sharedlib_members, /* tp_members */
- NULL, /* tp_getset */
+ NULL, /* tp_methods */
+ NULL, /* tp_members */
+ gdb_sharedlib_getset, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
@@ -122,9 +96,6 @@ sr_py_gdb_sharedlib_new(PyTypeObject *object, PyObject *args, PyObject *kwds)
return PyErr_NoMemory();
so->sharedlib = sr_gdb_sharedlib_new();
- so->syms_ok = SYMS_OK;
- so->syms_wrong = SYMS_WRONG;
- so->syms_not_found = SYMS_NOT_FOUND;
return (PyObject *)so;
}
@@ -147,80 +118,26 @@ sr_py_gdb_sharedlib_str(PyObject *self)
/* getters & setters */
-/* function_name */
-PyObject *
-sr_py_gdb_sharedlib_get_from(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("l", ((struct sr_py_gdb_sharedlib*)self)->sharedlib->from);
-}
-
-PyObject *
-sr_py_gdb_sharedlib_set_from(PyObject *self, PyObject *args)
-{
- unsigned long long newvalue;
- if (!PyArg_ParseTuple(args, "l", &newvalue))
- return NULL;
-
- ((struct sr_py_gdb_sharedlib *)self)->sharedlib->from = newvalue;
- Py_RETURN_NONE;
-}
-
PyObject *
-sr_py_gdb_sharedlib_get_to(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("l", ((struct sr_py_gdb_sharedlib*)self)->sharedlib->to);
-}
-
-PyObject *
-sr_py_gdb_sharedlib_set_to(PyObject *self, PyObject *args)
-{
- unsigned long long newvalue;
- if (!PyArg_ParseTuple(args, "l", &newvalue))
- return NULL;
-
- ((struct sr_py_gdb_sharedlib *)self)->sharedlib->to = newvalue;
- Py_RETURN_NONE;
-}
-
-PyObject *
-sr_py_gdb_sharedlib_get_symbols(PyObject *self, PyObject *args)
+sr_py_gdb_sharedlib_get_symbols(PyObject *self, void *data)
{
return Py_BuildValue("i", ((struct sr_py_gdb_sharedlib*)self)->sharedlib->symbols);
}
-PyObject *
-sr_py_gdb_sharedlib_set_symbols(PyObject *self, PyObject *args)
+int
+sr_py_gdb_sharedlib_set_symbols(PyObject *self, PyObject *rhs, void *data)
{
- int newvalue;
- if (!PyArg_ParseTuple(args, "i", &newvalue))
- return NULL;
+ long newvalue = PyInt_AsLong(rhs);
+ if (PyErr_Occurred())
+ return -1;
if (newvalue != SYMS_OK && newvalue != SYMS_WRONG && newvalue != SYMS_NOT_FOUND)
{
PyErr_SetString(PyExc_ValueError, "Symbols must be either SYMS_OK, "
"SYMS_WRONG or SYMS_NOT_FOUND.");
- return NULL;
+ return -1;
}
((struct sr_py_gdb_sharedlib *)self)->sharedlib->symbols = newvalue;
- Py_RETURN_NONE;
-}
-
-PyObject *
-sr_py_gdb_sharedlib_get_soname(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_gdb_sharedlib*)self)->sharedlib->soname);
-}
-
-PyObject *
-sr_py_gdb_sharedlib_set_soname(PyObject *self, PyObject *args)
-{
- char *soname;
- if (!PyArg_ParseTuple(args, "s", &soname))
- return NULL;
-
- struct sr_py_gdb_sharedlib *this = (struct sr_py_gdb_sharedlib*)self;
- free(this->sharedlib->soname);
- this->sharedlib->soname = sr_strdup(soname);
- Py_RETURN_NONE;
+ return 0;
}
diff --git a/python/py_gdb_sharedlib.h b/python/py_gdb_sharedlib.h
index 1a6ca92..335a2e7 100644
--- a/python/py_gdb_sharedlib.h
+++ b/python/py_gdb_sharedlib.h
@@ -38,9 +38,6 @@ struct sr_py_gdb_sharedlib
{
PyObject_HEAD
struct sr_gdb_sharedlib *sharedlib;
- int syms_ok;
- int syms_wrong;
- int syms_not_found;
};
/* constructor */
@@ -55,14 +52,8 @@ void sr_py_gdb_sharedlib_free(PyObject *object);
PyObject *sr_py_gdb_sharedlib_str(PyObject *self);
/* getters & setters */
-PyObject *sr_py_gdb_sharedlib_get_from(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_sharedlib_set_from(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_sharedlib_get_to(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_sharedlib_set_to(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_sharedlib_get_soname(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_sharedlib_set_soname(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_sharedlib_get_symbols(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_sharedlib_set_symbols(PyObject *self, PyObject *args);
+PyObject *sr_py_gdb_sharedlib_get_symbols(PyObject *self, void *data);
+int sr_py_gdb_sharedlib_set_symbols(PyObject *self, PyObject *rhs, void *data);
#ifdef __cplusplus
}
diff --git a/python/py_gdb_thread.c b/python/py_gdb_thread.c
index dd48a90..7aed856 100644
--- a/python/py_gdb_thread.c
+++ b/python/py_gdb_thread.c
@@ -1,3 +1,4 @@
+#include "py_common.h"
#include "py_gdb_thread.h"
#include "py_gdb_frame.h"
#include "lib/strbuf.h"
@@ -11,11 +12,7 @@
"satyr.GdbThread(str) - parses str and fills the thread object\n" \
"satyr.GdbThread(str, only_funs=True) - parses list of function names"
-#define t_get_number_doc "Usage: thread.get_number()\n" \
- "Returns: positive integer - thread number"
-
-#define t_set_number_doc "Usage: thread.set_number(N)\n" \
- "N: positive integer - new thread number"
+#define t_number_doc "Thread number (positive integer)"
#define t_dup_doc "Usage: thread.dup()\n" \
"Returns: satyr.GdbThread - a new clone of thread\n" \
@@ -48,9 +45,6 @@
static PyMethodDef
gdb_thread_methods[] =
{
- /* getters & setters */
- { "get_number", sr_py_gdb_thread_get_number, METH_NOARGS, t_get_number_doc },
- { "set_number", sr_py_gdb_thread_set_number, METH_VARARGS, t_set_number_doc },
/* methods */
{ "cmp", sr_py_gdb_thread_cmp, METH_VARARGS, t_cmp_doc },
{ "dup", sr_py_gdb_thread_dup, METH_NOARGS, t_dup_doc },
@@ -67,6 +61,21 @@ gdb_thread_members[] =
{ 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
+#define GSOFF_C_STRUCT sr_gdb_thread
+GSOFF_START
+GSOFF_MEMBER(number)
+GSOFF_END
+
+static PyGetSetDef
+gdb_thread_getset[] =
+{
+ { (char*)"number", sr_py_getter_uint32, sr_py_setter_uint32, (char*)t_number_doc, &gsoff_number },
+ { NULL },
+};
+
PyTypeObject sr_py_gdb_thread_type =
{
PyObject_HEAD_INIT(NULL)
@@ -97,9 +106,9 @@ PyTypeObject sr_py_gdb_thread_type =
0, /* tp_weaklistoffset */
NULL, /* tp_iter */
NULL, /* tp_iternext */
- gdb_thread_methods, /* tp_methods */
- gdb_thread_members, /* tp_members */
- NULL, /* tp_getset */
+ gdb_thread_methods, /* tp_methods */
+ gdb_thread_members, /* tp_members */
+ gdb_thread_getset, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
@@ -301,32 +310,6 @@ sr_py_gdb_thread_str(PyObject *self)
return result;
}
-/* getters & setters */
-PyObject *
-sr_py_gdb_thread_get_number(PyObject *self, PyObject *args)
-{
- struct sr_py_gdb_thread *this = (struct sr_py_gdb_thread *)self;
- return Py_BuildValue("i", this->thread->number);
-}
-
-PyObject *
-sr_py_gdb_thread_set_number(PyObject *self, PyObject *args)
-{
- struct sr_py_gdb_thread *this = (struct sr_py_gdb_thread *)self;
- int newvalue;
- if (!PyArg_ParseTuple(args, "i", &newvalue))
- return NULL;
-
- if (newvalue < 0)
- {
- PyErr_SetString(PyExc_ValueError, "Thread number must not be negative.");
- return NULL;
- }
-
- this->thread->number = newvalue;
- Py_RETURN_NONE;
-}
-
/* methods */
PyObject *
sr_py_gdb_thread_dup(PyObject *self, PyObject *args)
diff --git a/python/py_gdb_thread.h b/python/py_gdb_thread.h
index 39da841..c2c4611 100644
--- a/python/py_gdb_thread.h
+++ b/python/py_gdb_thread.h
@@ -57,10 +57,6 @@ void sr_py_gdb_thread_free(PyObject *object);
/* str */
PyObject *sr_py_gdb_thread_str(PyObject *self);
-/* getters & setters */
-PyObject *sr_py_gdb_thread_get_number(PyObject *self, PyObject *args);
-PyObject *sr_py_gdb_thread_set_number(PyObject *self, PyObject *args);
-
/* methods */
PyObject *sr_py_gdb_thread_dup(PyObject *self, PyObject *args);
PyObject *sr_py_gdb_thread_cmp(PyObject *self, PyObject *args);
diff --git a/python/py_java_frame.c b/python/py_java_frame.c
index 212e8d9..f1b0491 100644
--- a/python/py_java_frame.c
+++ b/python/py_java_frame.c
@@ -17,6 +17,7 @@
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_java_frame.h"
#include "lib/location.h"
#include "lib/strbuf.h"
@@ -28,47 +29,13 @@
"satyr.JavaFrame() - creates an empty frame\n" \
"satyr.JavaFrame(str) - parses str and fills the frame object"
-#define f_get_name_doc "Usage: frame.get_name()\n" \
- "Returns: string - fully qualified domain name"
-
-#define f_set_name_doc "Usage: frame.set_name(newname)\n" \
- "newname: string - new name"
-
-#define f_get_file_name_doc "Usage: frame.get_file_name()\n" \
- "Returns: string - file name"
-
-#define f_set_file_name_doc "Usage: frame.set_file_name(newname)\n" \
- "newname: string - new file name"
-
-#define f_get_file_line_doc "Usage: frame.get_file_line()\n" \
- "Returns: unsigned int - file line"
-
-#define f_set_file_line_doc "Usage: frame.set_file_line(newline)\n" \
- "newline: unsigned int - new file line"
-
-#define f_get_class_path_doc "Usage: frame.get_class_path()\n" \
- "Returns: string - class path"
-
-#define f_set_class_path_doc "Usage: frame.set_class_path(newcp)\n" \
- "newcp: string - new class path"
-
-#define f_is_native_doc "Usage: frame.is_native()\n" \
- "Returns: boolean - true if method is native, always false if frame is exception"
-
-#define f_set_is_native_doc "Usage: frame.is_natives(state)\n" \
- "state: boolean - set is_native to state"
-
-#define f_is_exception_doc "Usage: frame.is_exception()\n" \
- "Returns: boolean - true if frame is an exception"
-
-#define f_set_is_exception_doc "Usage: frame.is_exceptions(state)\n" \
- "state: boolean - set is_exception to state"
-
-#define f_get_message_doc "Usage: frame.get_message()\n" \
- "Returns: string - exception message"
-
-#define f_set_message_doc "Usage: frame.set_message(newexc)\n" \
- "newexc: string - new exception message"
+#define f_name_doc "Fully qualified domain name (string)"
+#define f_file_name_doc "File name (string)"
+#define f_file_line_doc "File line (positive integer)"
+#define f_class_path_doc "Class path (string)"
+#define f_native_doc "True if method is native, always false if frame is an exception (bool)"
+#define f_exception_doc "True if frame is an exception frame (bool)"
+#define f_message_doc "Exception message (string)"
#define f_dup_doc "Usage: frame.dup()\n" \
"Returns: satyr.JavaFrame - a new clone of frame\n" \
@@ -86,27 +53,39 @@
static PyMethodDef
frame_methods[] =
{
- /* getters & setters */
- { "get_name", sr_py_java_frame_get_name, METH_NOARGS, f_get_name_doc },
- { "set_name", sr_py_java_frame_set_name, METH_VARARGS, f_set_name_doc },
- { "get_file_name", sr_py_java_frame_get_file_name, METH_NOARGS, f_get_file_name_doc },
- { "set_file_name", sr_py_java_frame_set_file_name, METH_VARARGS, f_set_file_name_doc },
- { "get_file_line", sr_py_java_frame_get_file_line, METH_NOARGS, f_get_file_line_doc },
- { "set_file_line", sr_py_java_frame_set_file_line, METH_VARARGS, f_set_file_line_doc },
- { "get_class_path", sr_py_java_frame_get_class_path, METH_NOARGS, f_get_class_path_doc },
- { "set_class_path", sr_py_java_frame_set_class_path, METH_VARARGS, f_set_class_path_doc },
- { "is_native", sr_py_java_frame_is_native, METH_NOARGS, f_is_native_doc },
- { "set_is_native", sr_py_java_frame_set_is_native, METH_VARARGS, f_set_is_native_doc },
- { "is_exception", sr_py_java_frame_is_exception, METH_NOARGS, f_is_exception_doc },
- { "set_is_exception", sr_py_java_frame_set_is_exception, METH_VARARGS, f_set_is_exception_doc },
- { "get_message", sr_py_java_frame_get_message, METH_NOARGS, f_get_message_doc },
- { "set_message", sr_py_java_frame_set_message, METH_VARARGS, f_set_message_doc },
/* methods */
- { "dup", sr_py_java_frame_dup, METH_NOARGS, f_dup_doc },
- { "cmp", sr_py_java_frame_cmp, METH_VARARGS, f_cmp_doc },
+ { "dup", sr_py_java_frame_dup, METH_NOARGS, f_dup_doc },
+ { "cmp", sr_py_java_frame_cmp, METH_VARARGS, f_cmp_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_frame
+#define GSOFF_PY_MEMBER frame
+#define GSOFF_C_STRUCT sr_java_frame
+GSOFF_START
+GSOFF_MEMBER(name),
+GSOFF_MEMBER(file_name),
+GSOFF_MEMBER(file_line),
+GSOFF_MEMBER(class_path),
+GSOFF_MEMBER(is_native),
+GSOFF_MEMBER(is_exception),
+GSOFF_MEMBER(message)
+GSOFF_END
+
+static PyGetSetDef
+frame_getset[] =
+{
+ { (char*)"name", sr_py_getter_string, sr_py_setter_string, (char*)f_name_doc, &gsoff_name },
+ { (char*)"file_name", sr_py_getter_string, sr_py_setter_string, (char*)f_file_name_doc, &gsoff_file_name },
+ { (char*)"file_line", sr_py_getter_uint32, sr_py_setter_uint32, (char*)f_file_line_doc, &gsoff_file_line },
+ { (char*)"class_path", sr_py_getter_string, sr_py_setter_string, (char*)f_class_path_doc, &gsoff_class_path },
+ { (char*)"is_native", sr_py_getter_bool, sr_py_setter_bool, (char*)f_native_doc, &gsoff_is_native },
+ { (char*)"is_exception", sr_py_getter_bool, sr_py_setter_bool, (char*)f_exception_doc, &gsoff_is_exception },
+ { (char*)"message", sr_py_getter_string, sr_py_setter_string, (char*)f_message_doc, &gsoff_message },
+ { NULL }
+};
+
PyTypeObject
sr_py_java_frame_type =
{
@@ -140,7 +119,7 @@ sr_py_java_frame_type =
NULL, /* tp_iternext */
frame_methods, /* tp_methods */
NULL, /* tp_members */
- NULL, /* tp_getset */
+ frame_getset, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
@@ -242,157 +221,6 @@ sr_py_java_frame_str(PyObject *self)
return result;
}
-/* getters & setters */
-
-/* name */
-PyObject *
-sr_py_java_frame_get_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_java_frame*)self)->frame->name);
-}
-
-PyObject *
-sr_py_java_frame_set_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_java_frame *frame = ((struct sr_py_java_frame*)self)->frame;
- free(frame->name);
- frame->name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* file_name */
-PyObject *
-sr_py_java_frame_get_file_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_java_frame*)self)->frame->file_name);
-}
-
-PyObject *
-sr_py_java_frame_set_file_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_java_frame *frame = ((struct sr_py_java_frame*)self)->frame;
- free(frame->file_name);
- frame->file_name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* file_line */
-PyObject *
-sr_py_java_frame_get_file_line(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("i", ((struct sr_py_java_frame*)self)->frame->file_line);
-}
-
-PyObject *
-sr_py_java_frame_set_file_line(PyObject *self, PyObject *args)
-{
- int newvalue;
- if (!PyArg_ParseTuple(args, "i", &newvalue))
- return NULL;
-
- if (newvalue < 0)
- {
- PyErr_SetString(PyExc_ValueError, "File line must not be negative.");
- return NULL;
- }
-
- struct sr_java_frame *frame = ((struct sr_py_java_frame*)self)->frame;
- frame->file_line = newvalue;
- Py_RETURN_NONE;
-}
-
-/* class_path */
-PyObject *
-sr_py_java_frame_get_class_path(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_java_frame*)self)->frame->class_path);
-}
-
-PyObject *
-sr_py_java_frame_set_class_path(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_java_frame *frame = ((struct sr_py_java_frame*)self)->frame;
- free(frame->class_path);
- frame->class_path = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* native */
-PyObject *
-sr_py_java_frame_is_native(PyObject *self, PyObject *args)
-{
- if (!((struct sr_py_java_frame*)self)->frame->is_native)
- Py_RETURN_FALSE;
-
- Py_RETURN_TRUE;
-}
-
-PyObject *
-sr_py_java_frame_set_is_native(PyObject *self, PyObject *args)
-{
- int boolvalue;
- if (!PyArg_ParseTuple(args, "i", &boolvalue))
- return NULL;
-
- struct sr_java_frame *frame = ((struct sr_py_java_frame*)self)->frame;
- frame->is_native = boolvalue;
- Py_RETURN_NONE;
-}
-
-/* exception */
-PyObject *
-sr_py_java_frame_is_exception(PyObject *self, PyObject *args)
-{
- if (!((struct sr_py_java_frame*)self)->frame->is_exception)
- Py_RETURN_FALSE;
-
- Py_RETURN_TRUE;
-}
-
-PyObject *
-sr_py_java_frame_set_is_exception(PyObject *self, PyObject *args)
-{
- int boolvalue;
- if (!PyArg_ParseTuple(args, "i", &boolvalue))
- return NULL;
-
- struct sr_java_frame *frame = ((struct sr_py_java_frame*)self)->frame;
- frame->is_exception = boolvalue;
- Py_RETURN_NONE;
-}
-
-/* message */
-PyObject *
-sr_py_java_frame_get_message(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_java_frame*)self)->frame->message);
-}
-
-PyObject *
-sr_py_java_frame_set_message(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_java_frame *frame = ((struct sr_py_java_frame*)self)->frame;
- free(frame->message);
- frame->message = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
/* methods */
PyObject *
sr_py_java_frame_dup(PyObject *self, PyObject *args)
diff --git a/python/py_java_frame.h b/python/py_java_frame.h
index a475acc..fead53a 100644
--- a/python/py_java_frame.h
+++ b/python/py_java_frame.h
@@ -56,22 +56,6 @@ void sr_py_java_frame_free(PyObject *object);
*/
PyObject *sr_py_java_frame_str(PyObject *self);
-/* getters & setters */
-PyObject *sr_py_java_frame_get_name(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_set_name(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_get_file_name(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_set_file_name(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_get_file_line(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_set_file_line(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_get_class_path(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_set_class_path(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_is_native(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_set_is_native(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_is_exception(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_set_is_exception(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_get_message(PyObject *self, PyObject *args);
-PyObject *sr_py_java_frame_set_message(PyObject *self, PyObject *args);
-
/* methods */
PyObject *sr_py_java_frame_dup(PyObject *self, PyObject *args);
PyObject *sr_py_java_frame_cmp(PyObject *self, PyObject *args);
diff --git a/python/py_java_thread.c b/python/py_java_thread.c
index b8f3452..4c926d6 100644
--- a/python/py_java_thread.c
+++ b/python/py_java_thread.c
@@ -1,3 +1,4 @@
+#include "py_common.h"
#include "py_java_thread.h"
#include "py_java_frame.h"
#include "lib/strbuf.h"
@@ -12,11 +13,7 @@
"satyr.JavaThread(str) - parses str and fills the thread object\n" \
"satyr.JavaThread(str, only_funs=True) - parses list of function names"
-#define t_get_name_doc "Usage: thread.get_name()\n" \
- "Returns: string - thread name"
-
-#define t_set_name_doc "Usage: thread.set_number(newname)\n" \
- "newname: string - new thread name"
+#define t_name_doc "Thread name (string)"
#define t_dup_doc "Usage: thread.dup()\n" \
"Returns: satyr.JavaThread - a new clone of thread\n" \
@@ -49,9 +46,6 @@
static PyMethodDef
java_thread_methods[] =
{
- /* getters & setters */
- { "get_number", sr_py_java_thread_get_name, METH_NOARGS, t_get_name_doc },
- { "set_number", sr_py_java_thread_set_name, METH_VARARGS, t_set_name_doc },
/* methods */
{ "cmp", sr_py_java_thread_cmp, METH_VARARGS, t_cmp_doc },
{ "dup", sr_py_java_thread_dup, METH_NOARGS, t_dup_doc },
@@ -68,6 +62,21 @@ java_thread_members[] =
{ 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
+#define GSOFF_C_STRUCT sr_java_thread
+GSOFF_START
+GSOFF_MEMBER(name)
+GSOFF_END
+
+static PyGetSetDef
+java_thread_getset[] =
+{
+ { (char*)"name", sr_py_getter_string, sr_py_setter_string, (char*)t_name_doc, &gsoff_name },
+ { NULL },
+};
+
PyTypeObject sr_py_java_thread_type =
{
PyObject_HEAD_INIT(NULL)
@@ -100,7 +109,7 @@ PyTypeObject sr_py_java_thread_type =
NULL, /* tp_iternext */
java_thread_methods, /* tp_methods */
java_thread_members, /* tp_members */
- NULL, /* tp_getset */
+ java_thread_getset, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
@@ -271,29 +280,6 @@ sr_py_java_thread_str(PyObject *self)
return result;
}
-/* getters & setters */
-
-/* name */
-PyObject *
-sr_py_java_thread_get_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_java_thread*)self)->thread->name);
-}
-
-PyObject *
-sr_py_java_thread_set_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_java_thread *thread = ((struct sr_py_java_thread*)self)->thread;
- free(thread->name);
- thread->name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-
/* methods */
PyObject *
sr_py_java_thread_dup(PyObject *self, PyObject *args)
diff --git a/python/py_java_thread.h b/python/py_java_thread.h
index 7d347e5..a0754c5 100644
--- a/python/py_java_thread.h
+++ b/python/py_java_thread.h
@@ -57,10 +57,6 @@ void sr_py_java_thread_free(PyObject *object);
/* str */
PyObject *sr_py_java_thread_str(PyObject *self);
-/* getters & setters */
-PyObject *sr_py_java_thread_get_name(PyObject *self, PyObject *args);
-PyObject *sr_py_java_thread_set_name(PyObject *self, PyObject *args);
-
/* methods */
PyObject *sr_py_java_thread_dup(PyObject *self, PyObject *args);
PyObject *sr_py_java_thread_cmp(PyObject *self, PyObject *args);
diff --git a/python/py_koops_frame.c b/python/py_koops_frame.c
index e6dad1e..cf6a835 100644
--- a/python/py_koops_frame.c
+++ b/python/py_koops_frame.c
@@ -17,6 +17,7 @@
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_koops_frame.h"
#include <inttypes.h>
@@ -31,74 +32,17 @@
"satyr.KerneloopsFrame() - creates an empty frame\n" \
"satyr.KerneloopsFrame(str) - parses str and fills the frame object"
-#define f_get_reliable_doc "Usage: frame.get_reliable()\n" \
- "Returns: boolean - is this entry reliable"
-
-#define f_set_reliable_doc "Usage: frame.set_address(state)\n" \
- "state: boolean - set reliability to state"
-
-#define f_get_address_doc "Usage: frame.get_address()\n" \
- "Returns: positive long integer - address"
-
-#define f_set_address_doc "Usage: frame.set_address(N)\n" \
- "N: positive long integer - new address"
-
-#define f_get_function_name_doc "Usage: frame.get_function_name()\n" \
- "Returns: string - function name"
-
-#define f_set_function_name_doc "Usage: frame.set_function_name(newname)\n" \
- "newname: string - new function name"
-
-#define f_get_function_offset_doc "Usage: frame.get_function_offset()\n" \
- "Returns: positive long integer - function offset"
-
-#define f_set_function_offset_doc "Usage: frame.set_function_offset(newoffset)\n" \
- "newoffset: positive long integer - new function offset"
-
-#define f_get_function_length_doc "Usage: frame.get_function_length()\n" \
- "Returns: positive long integer - function length"
-
-#define f_set_function_length_doc "Usage: frame.set_function_length(newlength)\n" \
- "newlength: positive long integer - new function length"
-
-#define f_get_module_name_doc "Usage: frame.get_module_name()\n" \
- "Returns: string - module name"
-
-#define f_set_module_name_doc "Usage: frame.set_module_name(newname)\n" \
- "newname: string - new module name"
-
-
-
-#define f_get_from_address_doc "Usage: frame.get_from_address()\n" \
- "Returns: positive long integer - from address"
-
-#define f_set_from_address_doc "Usage: frame.set_from_address(N)\n" \
- "N: positive long integer - new from address"
-
-#define f_get_from_function_name_doc "Usage: frame.get_from_function_name()\n" \
- "Returns: string - from function name"
-
-#define f_set_from_function_name_doc "Usage: frame.set_from_function_name(newname)\n" \
- "newname: string - new from function name"
-
-#define f_get_from_function_offset_doc "Usage: frame.get_from_function_offset()\n" \
- "Returns: positive long integer - from function offset"
-
-#define f_set_from_function_offset_doc "Usage: frame.set_from_function_offset(newoffset)\n" \
- "newoffset: positive long integer - new from function offset"
-
-#define f_get_from_function_length_doc "Usage: frame.get_from_function_length()\n" \
- "Returns: positive long integer - from function length"
-
-#define f_set_from_function_length_doc "Usage: frame.set_from_function_length(newlength)\n" \
- "newlength: positive long integer - new from function length"
-
-#define f_get_from_module_name_doc "Usage: frame.get_from_module_name()\n" \
- "Returns: string - from module name"
-
-#define f_set_from_module_name_doc "Usage: frame.set_from_module_name(newname)\n" \
- "newname: string - new from module name"
-
+#define f_reliable_doc "True if the the frame is guaranteed to be real (bool)"
+#define f_address_doc "Address of the current instruction (long)"
+#define f_function_name_doc "Function name (string)"
+#define f_function_offset_doc "Function offset (long)"
+#define f_function_length_doc "Function length (long)"
+#define f_module_name_doc "Module owning the function (string)"
+#define f_from_address_doc "Address of the caller's instruction (long)"
+#define f_from_function_name_doc "Caller function name (string)"
+#define f_from_function_offset_doc "Caller function offset (long)"
+#define f_from_function_length_doc "Caller function length (long)"
+#define f_from_module_name_doc "Module owning the caller function (string)"
#define f_dup_doc "Usage: frame.dup()\n" \
"Returns: satyr.KerneloopsFrame - a new clone of frame\n" \
@@ -116,36 +60,47 @@
static PyMethodDef
frame_methods[] =
{
- /* getters & setters */
- { "get_reliable", sr_py_koops_frame_get_reliable, METH_NOARGS, f_get_reliable_doc },
- { "set_reliable", sr_py_koops_frame_set_reliable, METH_VARARGS, f_set_reliable_doc },
- { "get_address", sr_py_koops_frame_get_address, METH_NOARGS, f_get_address_doc },
- { "set_address", sr_py_koops_frame_set_address, METH_VARARGS, f_set_address_doc },
- { "get_function_name", sr_py_koops_frame_get_function_name, METH_NOARGS, f_get_function_name_doc },
- { "set_function_name", sr_py_koops_frame_set_function_name, METH_VARARGS, f_set_function_name_doc },
- { "get_function_offset", sr_py_koops_frame_get_function_offset, METH_NOARGS, f_get_function_offset_doc },
- { "set_function_offset", sr_py_koops_frame_set_function_offset, METH_VARARGS, f_set_function_offset_doc },
- { "get_function_length", sr_py_koops_frame_get_function_length, METH_NOARGS, f_get_function_length_doc },
- { "set_function_length", sr_py_koops_frame_set_function_length, METH_VARARGS, f_set_function_length_doc },
- { "get_module_name", sr_py_koops_frame_get_module_name, METH_NOARGS, f_get_module_name_doc },
- { "set_module_name", sr_py_koops_frame_set_module_name, METH_VARARGS, f_set_module_name_doc },
- { "get_from_address", sr_py_koops_frame_get_from_address, METH_NOARGS, f_get_from_address_doc },
- { "set_from_address", sr_py_koops_frame_set_from_address, METH_VARARGS, f_set_from_address_doc },
- { "get_from_function_name", sr_py_koops_frame_get_from_function_name, METH_NOARGS, f_get_from_function_name_doc },
- { "set_from_function_name", sr_py_koops_frame_set_from_function_name, METH_VARARGS, f_set_from_function_name_doc },
- { "get_from_function_offset", sr_py_koops_frame_get_from_function_offset, METH_NOARGS, f_get_from_function_offset_doc },
- { "set_from_function_offset", sr_py_koops_frame_set_from_function_offset, METH_VARARGS, f_set_from_function_offset_doc },
- { "get_from_function_length", sr_py_koops_frame_get_from_function_length, METH_NOARGS, f_get_from_function_length_doc },
- { "set_from_function_length", sr_py_koops_frame_set_from_function_length, METH_VARARGS, f_set_from_function_length_doc },
- { "get_from_module_name", sr_py_koops_frame_get_from_module_name, METH_NOARGS, f_get_from_module_name_doc },
- { "set_from_module_name", sr_py_koops_frame_set_from_module_name, METH_VARARGS, f_set_from_module_name_doc },
-
/* methods */
{ "dup", sr_py_koops_frame_dup, METH_NOARGS, f_dup_doc },
{ "cmp", sr_py_koops_frame_cmp, METH_VARARGS, f_cmp_doc },
{ NULL },
};
+/* See python/py_common.h and python/py_gdb_frame.c for generic getters/setters documentation. */
+#define GSOFF_PY_STRUCT sr_py_koops_frame
+#define GSOFF_PY_MEMBER frame
+#define GSOFF_C_STRUCT sr_koops_frame
+GSOFF_START
+GSOFF_MEMBER(address),
+GSOFF_MEMBER(reliable),
+GSOFF_MEMBER(function_name),
+GSOFF_MEMBER(function_offset),
+GSOFF_MEMBER(function_length),
+GSOFF_MEMBER(module_name),
+GSOFF_MEMBER(from_address),
+GSOFF_MEMBER(from_function_name),
+GSOFF_MEMBER(from_function_offset),
+GSOFF_MEMBER(from_function_length),
+GSOFF_MEMBER(from_module_name)
+GSOFF_END
+
+static PyGetSetDef
+frame_getset[] =
+{
+ { (char*)"reliable", sr_py_getter_bool, sr_py_setter_bool, (char*)f_reliable_doc, &gsoff_reliable },
+ { (char*)"address", sr_py_getter_uint64, sr_py_setter_uint64, (char*)f_address_doc, &gsoff_address },
+ { (char*)"function_name", sr_py_getter_string, sr_py_setter_string, (char*)f_function_name_doc, &gsoff_function_name },
+ { (char*)"function_offset", sr_py_getter_uint64, sr_py_setter_uint64, (char*)f_function_offset_doc, &gsoff_function_offset },
+ { (char*)"function_length", sr_py_getter_uint64, sr_py_setter_uint64, (char*)f_function_length_doc, &gsoff_function_length },
+ { (char*)"module_name", sr_py_getter_string, sr_py_setter_string, (char*)f_module_name_doc, &gsoff_module_name },
+ { (char*)"from_address", sr_py_getter_uint64, sr_py_setter_uint64, (char*)f_from_address_doc, &gsoff_from_address },
+ { (char*)"from_function_name", sr_py_getter_string, sr_py_setter_string, (char*)f_from_function_name_doc, &gsoff_from_function_name },
+ { (char*)"from_function_offset", sr_py_getter_uint64, sr_py_setter_uint64, (char*)f_from_function_offset_doc, &gsoff_from_function_offset },
+ { (char*)"from_function_length", sr_py_getter_uint64, sr_py_setter_uint64, (char*)f_from_function_length_doc, &gsoff_from_function_length },
+ { (char*)"from_module_name", sr_py_getter_string, sr_py_setter_string, (char*)f_from_module_name_doc, &gsoff_from_module_name },
+ { NULL },
+};
+
PyTypeObject
sr_py_koops_frame_type =
{
@@ -179,7 +134,7 @@ sr_py_koops_frame_type =
NULL, /* tp_iternext */
frame_methods, /* tp_methods */
NULL, /* tp_members */
- NULL, /* tp_getset */
+ frame_getset, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
@@ -278,231 +233,6 @@ sr_py_koops_frame_str(PyObject *self)
return result;
}
-/* getters & setters */
-
-/* reliable */
-PyObject *
-sr_py_koops_frame_get_reliable(PyObject *self, PyObject *args)
-{
- if (!((struct sr_py_koops_frame*)self)->frame->reliable)
- Py_RETURN_FALSE;
-
- Py_RETURN_TRUE;
-}
-
-PyObject *
-sr_py_koops_frame_set_reliable(PyObject *self, PyObject *args)
-{
- int boolvalue;
- if (!PyArg_ParseTuple(args, "i", &boolvalue))
- return NULL;
-
- struct sr_koops_frame *frame = ((struct sr_py_koops_frame*)self)->frame;
- frame->reliable = boolvalue;
- Py_RETURN_NONE;
-}
-
-/* address */
-PyObject *
-sr_py_koops_frame_get_address(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("K",
- (unsigned long long)(((struct sr_py_koops_frame*)self)->frame->address));
-}
-
-PyObject *
-sr_py_koops_frame_set_address(PyObject *self, PyObject *args)
-{
- unsigned long long newvalue;
- if (!PyArg_ParseTuple(args, "K", &newvalue))
- return NULL;
-
- struct sr_koops_frame *frame = ((struct sr_py_koops_frame*)self)->frame;
- frame->address = newvalue;
- Py_RETURN_NONE;
-}
-
-/* from_address */
-PyObject *
-sr_py_koops_frame_get_from_address(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("K",
- (unsigned long long)(((struct sr_py_koops_frame*)self)->frame->from_address));
-}
-
-PyObject *
-sr_py_koops_frame_set_from_address(PyObject *self, PyObject *args)
-{
- unsigned long long newvalue;
- if (!PyArg_ParseTuple(args, "K", &newvalue))
- return NULL;
-
- struct sr_koops_frame *frame = ((struct sr_py_koops_frame*)self)->frame;
- frame->from_address = newvalue;
- Py_RETURN_NONE;
-}
-
-
-/* function_name */
-PyObject *
-sr_py_koops_frame_get_function_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_koops_frame*)self)->frame->function_name);
-}
-
-PyObject *
-sr_py_koops_frame_set_function_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_koops_frame *frame = ((struct sr_py_koops_frame*)self)->frame;
- free(frame->function_name);
- frame->function_name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* from_function_name */
-PyObject *
-sr_py_koops_frame_get_from_function_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_koops_frame*)self)->frame->from_function_name);
-}
-
-PyObject *
-sr_py_koops_frame_set_from_function_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_koops_frame *frame = ((struct sr_py_koops_frame*)self)->frame;
- free(frame->function_name);
- frame->from_function_name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* function_offset */
-PyObject *
-sr_py_koops_frame_get_function_offset(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("K",
- (unsigned long long)(((struct sr_py_koops_frame*)self)->frame->function_offset));
-}
-
-PyObject *
-sr_py_koops_frame_set_function_offset(PyObject *self, PyObject *args)
-{
- unsigned long long newvalue;
- if (!PyArg_ParseTuple(args, "K", &newvalue))
- return NULL;
-
- struct sr_koops_frame *frame = ((struct sr_py_koops_frame*)self)->frame;
- frame->function_offset = newvalue;
- Py_RETURN_NONE;
-}
-
-/* from_function_offset */
-PyObject *
-sr_py_koops_frame_get_from_function_offset(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("K",
- (unsigned long long)(((struct sr_py_koops_frame*)self)->frame->from_function_offset));
-}
-
-PyObject *
-sr_py_koops_frame_set_from_function_offset(PyObject *self, PyObject *args)
-{
- unsigned long long newvalue;
- if (!PyArg_ParseTuple(args, "K", &newvalue))
- return NULL;
-
- struct sr_koops_frame *frame = ((struct sr_py_koops_frame*)self)->frame;
- frame->from_function_offset = newvalue;
- Py_RETURN_NONE;
-}
-
-/* function_length */
-PyObject *
-sr_py_koops_frame_get_function_length(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("K",
- (unsigned long long)(((struct sr_py_koops_frame*)self)->frame->function_length));
-}
-
-PyObject *
-sr_py_koops_frame_set_function_length(PyObject *self, PyObject *args)
-{
- unsigned long long newvalue;
- if (!PyArg_ParseTuple(args, "K", &newvalue))
- return NULL;
-
- struct sr_koops_frame *frame = ((struct sr_py_koops_frame*)self)->frame;
- frame->function_length = newvalue;
- Py_RETURN_NONE;
-}
-
-/* from_function_length */
-PyObject *
-sr_py_koops_frame_get_from_function_length(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("K",
- (unsigned long long)(((struct sr_py_koops_frame*)self)->frame->from_function_length));
-}
-
-PyObject *
-sr_py_koops_frame_set_from_function_length(PyObject *self, PyObject *args)
-{
- unsigned long long newvalue;
- if (!PyArg_ParseTuple(args, "K", &newvalue))
- return NULL;
-
- struct sr_koops_frame *frame = ((struct sr_py_koops_frame*)self)->frame;
- frame->from_function_length = newvalue;
- Py_RETURN_NONE;
-}
-
-/* module_name */
-PyObject *
-sr_py_koops_frame_get_module_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_koops_frame*)self)->frame->module_name);
-}
-
-PyObject *
-sr_py_koops_frame_set_module_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_koops_frame *frame = ((struct sr_py_koops_frame*)self)->frame;
- free(frame->module_name);
- frame->module_name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* from_module_name */
-PyObject *
-sr_py_koops_frame_get_from_module_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_koops_frame*)self)->frame->from_module_name);
-}
-
-PyObject *
-sr_py_koops_frame_set_from_module_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_koops_frame *frame = ((struct sr_py_koops_frame*)self)->frame;
- free(frame->module_name);
- frame->from_module_name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
/* methods */
PyObject *
sr_py_koops_frame_dup(PyObject *self, PyObject *args)
diff --git a/python/py_koops_frame.h b/python/py_koops_frame.h
index 51dc4d9..e9c13f5 100644
--- a/python/py_koops_frame.h
+++ b/python/py_koops_frame.h
@@ -56,31 +56,6 @@ void sr_py_koops_frame_free(PyObject *object);
*/
PyObject *sr_py_koops_frame_str(PyObject *self);
-/* getters & setters */
-PyObject *sr_py_koops_frame_get_reliable(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_set_reliable(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_get_address(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_set_address(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_get_function_name(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_set_function_name(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_get_function_offset(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_set_function_offset(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_get_function_length(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_set_function_length(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_get_module_name(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_set_module_name(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_get_from_address(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_set_from_address(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_get_from_function_name(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_set_from_function_name(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_get_from_function_offset(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_set_from_function_offset(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_get_from_function_length(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_set_from_function_length(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_get_from_module_name(PyObject *self, PyObject *args);
-PyObject *sr_py_koops_frame_set_from_module_name(PyObject *self, PyObject *args);
-
-
/* methods */
PyObject *sr_py_koops_frame_dup(PyObject *self, PyObject *args);
PyObject *sr_py_koops_frame_cmp(PyObject *self, PyObject *args);
diff --git a/python/py_koops_stacktrace.c b/python/py_koops_stacktrace.c
index fcb367e..cd74fd9 100644
--- a/python/py_koops_stacktrace.c
+++ b/python/py_koops_stacktrace.c
@@ -20,15 +20,12 @@
"Normalizes the stacktrace."
#define b_frames_doc "A list containing frames"
-#define b_get_modules_doc "Usage: stacktrace.get_modules()\n" \
- "Returns: list of strings - loaded modules at time of the event"
+#define b_modules_doc "Modules loaded at the time of the event (list of strings)"
static PyMethodDef
koops_stacktrace_methods[] =
{
- /* getters & setters */
- { "get_modules", sr_py_koops_stacktrace_get_modules, METH_NOARGS, b_get_modules_doc },
/* methods */
{ "dup", sr_py_koops_stacktrace_dup, METH_NOARGS, b_dup_doc },
{ "normalize", sr_py_koops_stacktrace_normalize, METH_NOARGS, b_normalize_doc },
@@ -42,6 +39,13 @@ koops_stacktrace_members[] =
{ NULL },
};
+static PyGetSetDef
+koops_stacktrace_getset[] =
+{
+ { (char*)"modules", sr_py_koops_stacktrace_get_modules, sr_py_koops_stacktrace_set_modules, (char*)b_modules_doc, NULL },
+ { NULL },
+};
+
PyTypeObject sr_py_koops_stacktrace_type = {
PyObject_HEAD_INIT(NULL)
0,
@@ -73,7 +77,7 @@ PyTypeObject sr_py_koops_stacktrace_type = {
NULL, /* tp_iternext */
koops_stacktrace_methods, /* tp_methods */
koops_stacktrace_members, /* tp_members */
- NULL, /* tp_getset */
+ koops_stacktrace_getset, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
@@ -135,7 +139,7 @@ koops_stacktrace_prepare_linked_list(struct sr_py_koops_stacktrace *stacktrace)
}
PyObject *
-sr_py_koops_stacktrace_get_modules(PyObject *self, PyObject *args)
+sr_py_koops_stacktrace_get_modules(PyObject *self, void *data)
{
struct sr_koops_stacktrace *st = ((struct sr_py_koops_stacktrace*)self)->stacktrace;
char **iter = st->modules;
@@ -152,6 +156,13 @@ sr_py_koops_stacktrace_get_modules(PyObject *self, PyObject *args)
return result;
}
+int
+sr_py_koops_stacktrace_set_modules(PyObject *self, PyObject *rhs, void *data)
+{
+ PyErr_SetString(PyExc_NotImplementedError, "Setting module list is not implemented.");
+ return -1;
+}
+
PyObject *
koops_frame_linked_list_to_python_list(struct sr_koops_stacktrace *stacktrace)
{
diff --git a/python/py_koops_stacktrace.h b/python/py_koops_stacktrace.h
index 6c4ce89..b36b555 100644
--- a/python/py_koops_stacktrace.h
+++ b/python/py_koops_stacktrace.h
@@ -53,7 +53,8 @@ void sr_py_koops_stacktrace_free(PyObject *object);
PyObject *sr_py_koops_stacktrace_str(PyObject *self);
/* getters & setters */
-PyObject *sr_py_koops_stacktrace_get_modules(PyObject *self, PyObject *args);
+PyObject *sr_py_koops_stacktrace_get_modules(PyObject *self, void *data);
+int sr_py_koops_stacktrace_set_modules(PyObject *self, PyObject *rhs, void *data);
/* methods */
PyObject *sr_py_koops_stacktrace_dup(PyObject *self, PyObject *args);
diff --git a/python/py_module.c b/python/py_module.c
index e48718e..4eb3505 100644
--- a/python/py_module.c
+++ b/python/py_module.c
@@ -13,6 +13,8 @@
#include "py_java_stacktrace.h"
#include "py_metrics.h"
+#include "lib/gdb_sharedlib.h"
+
static PyMethodDef
module_methods[]=
{
@@ -136,6 +138,10 @@ init_satyr()
PyModule_AddObject(module, "GdbSharedlib",
(PyObject *)&sr_py_gdb_sharedlib_type);
+ PyModule_AddIntMacro(module, SYMS_OK);
+ PyModule_AddIntMacro(module, SYMS_NOT_FOUND);
+ PyModule_AddIntMacro(module, SYMS_WRONG);
+
Py_INCREF(&sr_py_koops_frame_type);
PyModule_AddObject(module, "KerneloopsFrame",
(PyObject *)&sr_py_koops_frame_type);
diff --git a/python/py_python_frame.c b/python/py_python_frame.c
index 0cf16cb..79098c2 100644
--- a/python/py_python_frame.c
+++ b/python/py_python_frame.c
@@ -17,6 +17,7 @@
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_python_frame.h"
#include "lib/location.h"
#include "lib/strbuf.h"
@@ -28,35 +29,11 @@
"satyr.PythonFrame() - creates an empty frame\n" \
"satyr.PythonFrame(str) - parses str and fills the frame object"
-#define f_get_file_name_doc "Usage: frame.get_file_name()\n" \
- "Returns: string - file name"
-
-#define f_set_file_name_doc "Usage: frame.set_file_name(newname)\n" \
- "newname: string - new file name"
-
-#define f_get_file_line_doc "Usage: frame.get_file_line()\n" \
- "Returns: unsigned int - file line"
-
-#define f_set_file_line_doc "Usage: frame.set_file_line(newline)\n" \
- "newline: unsigned int - new file line"
-
-#define f_is_module_doc "Usage: frame.is_module()\n" \
- "Returns: boolean - is this entry from main module"
-
-#define f_set_is_module_doc "Usage: frame.is_modules(state)\n" \
- "state: boolean - set is_module to state"
-
-#define f_get_function_name_doc "Usage: frame.get_function_name()\n" \
- "Returns: string - function name"
-
-#define f_set_function_name_doc "Usage: frame.set_function_name(newname)\n" \
- "newname: string - new function name"
-
-#define f_get_line_contents_doc "Usage: frame.get_line_contents()\n" \
- "Returns: string - remaining line contents"
-
-#define f_set_line_contents_doc "Usage: frame.set_line_contents(newname)\n" \
- "newname: string - new line contents"
+#define f_file_name_doc "Source file name (string)"
+#define f_file_line_doc "Source line number (positive integer)"
+#define f_is_module_doc "True if the frame is from the main module (bool)"
+#define f_function_name_doc "Function name (string)"
+#define f_line_contents_doc "Remaining line contents (string)"
#define f_dup_doc "Usage: frame.dup()\n" \
"Returns: satyr.PythonFrame - a new clone of frame\n" \
@@ -74,20 +51,32 @@
static PyMethodDef
frame_methods[] =
{
- /* getters & setters */
- { "get_file_name", sr_py_python_frame_get_file_name, METH_NOARGS, f_get_file_name_doc },
- { "set_file_name", sr_py_python_frame_set_file_name, METH_VARARGS, f_set_file_name_doc },
- { "get_file_line", sr_py_python_frame_get_file_line, METH_NOARGS, f_get_file_line_doc },
- { "set_file_line", sr_py_python_frame_set_file_line, METH_VARARGS, f_set_file_line_doc },
- { "is_module", sr_py_python_frame_is_module, METH_NOARGS, f_is_module_doc },
- { "set_is_module", sr_py_python_frame_set_is_module, METH_VARARGS, f_set_is_module_doc },
- { "get_function_name", sr_py_python_frame_get_function_name, METH_NOARGS, f_get_function_name_doc },
- { "set_function_name", sr_py_python_frame_set_function_name, METH_VARARGS, f_set_function_name_doc },
- { "get_line_contents", sr_py_python_frame_get_line_contents, METH_NOARGS, f_get_line_contents_doc },
- { "set_line_contents", sr_py_python_frame_set_line_contents, METH_VARARGS, f_set_line_contents_doc },
/* methods */
- { "dup", sr_py_python_frame_dup, METH_NOARGS, f_dup_doc },
- { "cmp", sr_py_python_frame_cmp, METH_VARARGS, f_cmp_doc },
+ { "dup", sr_py_python_frame_dup, METH_NOARGS, f_dup_doc },
+ { "cmp", sr_py_python_frame_cmp, METH_VARARGS, f_cmp_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_frame
+#define GSOFF_PY_MEMBER frame
+#define GSOFF_C_STRUCT sr_python_frame
+GSOFF_START
+GSOFF_MEMBER(file_name),
+GSOFF_MEMBER(file_line),
+GSOFF_MEMBER(is_module),
+GSOFF_MEMBER(function_name),
+GSOFF_MEMBER(line_contents)
+GSOFF_END
+
+static PyGetSetDef
+frame_getset[] =
+{
+ { (char*)"file_name", sr_py_getter_string, sr_py_setter_string, (char*)f_file_name_doc, &gsoff_file_name },
+ { (char*)"file_line", sr_py_getter_uint32, sr_py_setter_uint32, (char*)f_file_line_doc, &gsoff_file_line },
+ { (char*)"is_module", sr_py_getter_bool, sr_py_setter_bool, (char*)f_is_module_doc, &gsoff_is_module },
+ { (char*)"function_name", sr_py_getter_string, sr_py_setter_string, (char*)f_function_name_doc, &gsoff_function_name },
+ { (char*)"line_contents", sr_py_getter_string, sr_py_setter_string, (char*)f_line_contents_doc, &gsoff_line_contents },
{ NULL },
};
@@ -124,7 +113,7 @@ sr_py_python_frame_type =
NULL, /* tp_iternext */
frame_methods, /* tp_methods */
NULL, /* tp_members */
- NULL, /* tp_getset */
+ frame_getset, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
@@ -212,115 +201,6 @@ sr_py_python_frame_str(PyObject *self)
return result;
}
-/* getters & setters */
-
-/* file_name */
-PyObject *
-sr_py_python_frame_get_file_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_python_frame*)self)->frame->file_name);
-}
-
-PyObject *
-sr_py_python_frame_set_file_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_python_frame *frame = ((struct sr_py_python_frame*)self)->frame;
- free(frame->file_name);
- frame->file_name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* file_line */
-PyObject *
-sr_py_python_frame_get_file_line(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("i", ((struct sr_py_python_frame*)self)->frame->file_line);
-}
-
-PyObject *
-sr_py_python_frame_set_file_line(PyObject *self, PyObject *args)
-{
- int newvalue;
- if (!PyArg_ParseTuple(args, "i", &newvalue))
- return NULL;
-
- if (newvalue < 0)
- {
- PyErr_SetString(PyExc_ValueError, "File line must not be negative.");
- return NULL;
- }
-
- struct sr_python_frame *frame = ((struct sr_py_python_frame*)self)->frame;
- frame->file_line = newvalue;
- Py_RETURN_NONE;
-}
-
-/* reliable */
-PyObject *
-sr_py_python_frame_is_module(PyObject *self, PyObject *args)
-{
- if (!((struct sr_py_python_frame*)self)->frame->is_module)
- Py_RETURN_FALSE;
-
- Py_RETURN_TRUE;
-}
-
-PyObject *
-sr_py_python_frame_set_is_module(PyObject *self, PyObject *args)
-{
- int boolvalue;
- if (!PyArg_ParseTuple(args, "i", &boolvalue))
- return NULL;
-
- struct sr_python_frame *frame = ((struct sr_py_python_frame*)self)->frame;
- frame->is_module = boolvalue;
- Py_RETURN_NONE;
-}
-
-/* function_name */
-PyObject *
-sr_py_python_frame_get_function_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_python_frame*)self)->frame->function_name);
-}
-
-PyObject *
-sr_py_python_frame_set_function_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_python_frame *frame = ((struct sr_py_python_frame*)self)->frame;
- free(frame->function_name);
- frame->function_name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* line_contents */
-PyObject *
-sr_py_python_frame_get_line_contents(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_python_frame*)self)->frame->line_contents);
-}
-
-PyObject *
-sr_py_python_frame_set_line_contents(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_python_frame *frame = ((struct sr_py_python_frame*)self)->frame;
- free(frame->line_contents);
- frame->line_contents = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
/* methods */
PyObject *
sr_py_python_frame_dup(PyObject *self, PyObject *args)
diff --git a/python/py_python_frame.h b/python/py_python_frame.h
index 95df450..f0848c2 100644
--- a/python/py_python_frame.h
+++ b/python/py_python_frame.h
@@ -56,18 +56,6 @@ void sr_py_python_frame_free(PyObject *object);
*/
PyObject *sr_py_python_frame_str(PyObject *self);
-/* getters & setters */
-PyObject *sr_py_python_frame_get_file_name(PyObject *self, PyObject *args);
-PyObject *sr_py_python_frame_set_file_name(PyObject *self, PyObject *args);
-PyObject *sr_py_python_frame_get_file_line(PyObject *self, PyObject *args);
-PyObject *sr_py_python_frame_set_file_line(PyObject *self, PyObject *args);
-PyObject *sr_py_python_frame_is_module(PyObject *self, PyObject *args);
-PyObject *sr_py_python_frame_set_is_module(PyObject *self, PyObject *args);
-PyObject *sr_py_python_frame_get_function_name(PyObject *self, PyObject *args);
-PyObject *sr_py_python_frame_set_function_name(PyObject *self, PyObject *args);
-PyObject *sr_py_python_frame_get_line_contents(PyObject *self, PyObject *args);
-PyObject *sr_py_python_frame_set_line_contents(PyObject *self, PyObject *args);
-
/* methods */
PyObject *sr_py_python_frame_dup(PyObject *self, PyObject *args);
PyObject *sr_py_python_frame_cmp(PyObject *self, PyObject *args);
diff --git a/python/py_python_stacktrace.c b/python/py_python_stacktrace.c
index 92af646..a0a5141 100644
--- a/python/py_python_stacktrace.c
+++ b/python/py_python_stacktrace.c
@@ -1,3 +1,4 @@
+#include "py_common.h"
#include "py_python_frame.h"
#include "py_python_stacktrace.h"
#include "lib/utils.h"
@@ -12,23 +13,9 @@
"satyr.PythonStacktrace() - creates an empty python stacktrace\n" \
"satyr.PythonStacktrace(str) - parses str and fills the python stacktrace object"
-#define f_get_file_name_doc "Usage: frame.get_file_name()\n" \
- "Returns: string - file name"
-
-#define f_set_file_name_doc "Usage: frame.set_file_name(newname)\n" \
- "newname: string - new file name"
-
-#define f_get_file_line_doc "Usage: frame.get_file_line()\n" \
- "Returns: unsigned int - file line"
-
-#define f_set_file_line_doc "Usage: frame.set_file_line(newline)\n" \
- "newline: unsigned int - new file line"
-
-#define f_get_exception_name_doc "Usage: frame.get_exception_name()\n" \
- "Returns: string - function name"
-
-#define f_set_exception_name_doc "Usage: frame.set_exception_name(newname)\n" \
- "newname: string - new function name"
+#define f_file_name_doc "Source file name (string)"
+#define f_file_line_doc "Source line number (positive integer)"
+#define f_exception_name_doc "Exception type (string)"
#define f_dup_doc "Usage: stacktrace.dup()\n" \
"Returns: satyr.PythonStacktrace - a new clone of python stacktrace\n" \
@@ -46,16 +33,9 @@
static PyMethodDef
python_stacktrace_methods[] =
{
- /* getters & setters */
- { "get_file_name", sr_py_python_stacktrace_get_file_name, METH_NOARGS, f_get_file_name_doc },
- { "set_file_name", sr_py_python_stacktrace_set_file_name, METH_VARARGS, f_set_file_name_doc },
- { "get_file_line", sr_py_python_stacktrace_get_file_line, METH_NOARGS, f_get_file_line_doc },
- { "set_file_line", sr_py_python_stacktrace_set_file_line, METH_VARARGS, f_set_file_line_doc },
- { "get_exception_name", sr_py_python_stacktrace_get_exception_name, METH_NOARGS, f_get_exception_name_doc },
- { "set_exception_name", sr_py_python_stacktrace_set_exception_name, METH_VARARGS, f_set_exception_name_doc },
/* methods */
- { "dup", sr_py_python_stacktrace_dup, METH_NOARGS, f_dup_doc },
-// { "normalize", sr_py_python_stacktrace_normalize, METH_NOARGS, f_normalize_doc },
+ { "dup", sr_py_python_stacktrace_dup, METH_NOARGS, f_dup_doc },
+// { "normalize", sr_py_python_stacktrace_normalize, METH_NOARGS, f_normalize_doc },
{ NULL },
};
@@ -66,6 +46,25 @@ python_stacktrace_members[] =
{ 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
+#define GSOFF_C_STRUCT sr_python_stacktrace
+GSOFF_START
+GSOFF_MEMBER(file_name),
+GSOFF_MEMBER(file_line),
+GSOFF_MEMBER(exception_name)
+GSOFF_END
+
+static PyGetSetDef
+python_stacktrace_getset[] =
+{
+ { (char*)"file_name", sr_py_getter_string, sr_py_setter_string, (char*)f_file_name_doc, &gsoff_file_name },
+ { (char*)"file_line", sr_py_getter_uint32, sr_py_setter_uint32, (char*)f_file_line_doc, &gsoff_file_line },
+ { (char*)"exception_name", sr_py_getter_string, sr_py_setter_string, (char*)f_exception_name_doc, &gsoff_exception_name },
+ { NULL },
+};
+
PyTypeObject sr_py_python_stacktrace_type = {
PyObject_HEAD_INIT(NULL)
0,
@@ -97,7 +96,7 @@ PyTypeObject sr_py_python_stacktrace_type = {
NULL, /* tp_iternext */
python_stacktrace_methods, /* tp_methods */
python_stacktrace_members, /* tp_members */
- NULL, /* tp_getset */
+ python_stacktrace_getset, /* tp_getset */
NULL, /* tp_base */
NULL, /* tp_dict */
NULL, /* tp_descr_get */
@@ -268,73 +267,6 @@ sr_py_python_stacktrace_str(PyObject *self)
return result;
}
-/* getters & setters */
-
-/* file_name */
-PyObject *
-sr_py_python_stacktrace_get_file_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_python_stacktrace*)self)->stacktrace->file_name);
-}
-
-PyObject *
-sr_py_python_stacktrace_set_file_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_python_stacktrace *stacktrace = ((struct sr_py_python_stacktrace*)self)->stacktrace;
- free(stacktrace->file_name);
- stacktrace->file_name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
-/* file_line */
-PyObject *
-sr_py_python_stacktrace_get_file_line(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("i", ((struct sr_py_python_stacktrace*)self)->stacktrace->file_line);
-}
-
-PyObject *
-sr_py_python_stacktrace_set_file_line(PyObject *self, PyObject *args)
-{
- int newvalue;
- if (!PyArg_ParseTuple(args, "i", &newvalue))
- return NULL;
-
- if (newvalue < 0)
- {
- PyErr_SetString(PyExc_ValueError, "File line must not be negative.");
- return NULL;
- }
-
- struct sr_python_stacktrace *stacktrace = ((struct sr_py_python_stacktrace*)self)->stacktrace;
- stacktrace->file_line = newvalue;
- Py_RETURN_NONE;
-}
-
-/* exception_name */
-PyObject *
-sr_py_python_stacktrace_get_exception_name(PyObject *self, PyObject *args)
-{
- return Py_BuildValue("s", ((struct sr_py_python_stacktrace*)self)->stacktrace->exception_name);
-}
-
-PyObject *
-sr_py_python_stacktrace_set_exception_name(PyObject *self, PyObject *args)
-{
- char *newvalue;
- if (!PyArg_ParseTuple(args, "s", &newvalue))
- return NULL;
-
- struct sr_python_stacktrace *stacktrace = ((struct sr_py_python_stacktrace*)self)->stacktrace;
- free(stacktrace->file_name);
- stacktrace->file_name = sr_strdup(newvalue);
- Py_RETURN_NONE;
-}
-
/* methods */
PyObject *
sr_py_python_stacktrace_dup(PyObject *self, PyObject *args)
diff --git a/python/py_python_stacktrace.h b/python/py_python_stacktrace.h
index a5128b7..e8e1d31 100644
--- a/python/py_python_stacktrace.h
+++ b/python/py_python_stacktrace.h
@@ -52,15 +52,6 @@ void sr_py_python_stacktrace_free(PyObject *object);
/* str */
PyObject *sr_py_python_stacktrace_str(PyObject *self);
-/* getters & setters */
-PyObject *sr_py_python_stacktrace_get_file_name(PyObject *self, PyObject *args);
-PyObject *sr_py_python_stacktrace_set_file_name(PyObject *self, PyObject *args);
-PyObject *sr_py_python_stacktrace_get_file_line(PyObject *self, PyObject *args);
-PyObject *sr_py_python_stacktrace_set_file_line(PyObject *self, PyObject *args);
-PyObject *sr_py_python_stacktrace_get_exception_name(PyObject *self, PyObject *args);
-PyObject *sr_py_python_stacktrace_set_exception_name(PyObject *self, PyObject *args);
-
-
/* methods */
PyObject *sr_py_python_stacktrace_dup(PyObject *self, PyObject *args);
PyObject *sr_py_python_stacktrace_normalize(PyObject *self, PyObject *args);
diff --git a/tests/python/gdb.py b/tests/python/gdb.py
index 3a6b66f..54f0fbf 100755
--- a/tests/python/gdb.py
+++ b/tests/python/gdb.py
@@ -2,6 +2,7 @@
import os
import unittest
+from test_helpers import BindingsTestCase
try:
import _satyr as satyr
@@ -19,7 +20,7 @@ if not os.path.isfile(path):
with file(path) as f:
contents = f.read()
-class TestGdbStacktrace(unittest.TestCase):
+class TestGdbStacktrace(BindingsTestCase):
def setUp(self):
self.trace = satyr.GdbStacktrace(contents)
@@ -55,15 +56,24 @@ class TestGdbStacktrace(unittest.TestCase):
out = str(self.trace)
self.assertTrue(('Stacktrace with %d threads' % threads_expected) in out)
-class TestGdbThread(unittest.TestCase):
+class TestGdbThread(BindingsTestCase):
def setUp(self):
self.thread = satyr.GdbStacktrace(contents).threads[0]
-class TestGdbSharedlib(unittest.TestCase):
+ def test_getset(self):
+ self.assertGetSetCorrect(self.thread, 'number', 2, 9000)
+
+class TestGdbSharedlib(BindingsTestCase):
def setUp(self):
self.shlib = satyr.GdbStacktrace(contents).libs[0]
-class TestGdbFrame(unittest.TestCase):
+ def test_getset(self):
+ self.assertGetSetCorrect(self.shlib, 'start_address', 0x3ecd63c680, 10)
+ self.assertGetSetCorrect(self.shlib, 'end_address', 0x3ecd71f0f8, 20)
+ self.assertGetSetCorrect(self.shlib, 'symbols', satyr.SYMS_OK, satyr.SYMS_WRONG)
+ self.assertGetSetCorrect(self.shlib, 'soname', '/usr/lib64/libpython2.6.so.1.0', '/dev/null')
+
+class TestGdbFrame(BindingsTestCase):
def setUp(self):
self.frame = satyr.GdbStacktrace(contents).threads[0].frames[0]
@@ -75,20 +85,33 @@ class TestGdbFrame(unittest.TestCase):
def test_dup(self):
dup = self.frame.dup()
- self.assertEqual(dup.get_function_name(),
- self.frame.get_function_name())
+ self.assertEqual(dup.function_name,
+ self.frame.function_name)
- dup.set_function_name('other')
- self.assertNotEqual(dup.get_function_name(),
- self.frame.get_function_name())
+ dup.function_name = 'other'
+ self.assertNotEqual(dup.function_name,
+ self.frame.function_name)
def test_cmp(self):
dup = self.frame.dup()
self.assertEqual(dup.cmp(dup, 0), 0)
self.assertEqual(dup.cmp(self.frame, 0), 0)
self.assertEqual(dup.cmp(self.frame, 0), 0)
- dup.set_function_name('another')
+ dup.function_name = 'another'
self.assertNotEqual(dup.cmp(self.frame, 0), 0)
+ def test_getset(self):
+ self.assertGetSetCorrect(self.frame, 'function_name', 'write', 'foo bar')
+ self.assertGetSetCorrect(self.frame, 'function_type', None, 'Maybe Integer')
+ self.assertGetSetCorrect(self.frame, 'number', 0, 42)
+ self.assertGetSetCorrect(self.frame, 'source_file', '../sysdeps/unix/syscall-template.S', 'ok.c')
+ self.assertGetSetCorrect(self.frame, 'source_line', 82, 1337)
+ self.assertGetSetCorrect(self.frame, 'signal_handler_called', False, True)
+ self.assertGetSetCorrect(self.frame, 'address', 0x3ec220e48d, 0x666)
+ self.assertGetSetCorrect(self.frame, 'address', 0x666, 4398046511104L)
+ ## 2^66, this is expected to fail
+ #self.assertGetSetCorrect(self.frame, 'address', 4398046511104L, 73786976294838206464L)
+ self.assertGetSetCorrect(self.frame, 'library_name', None, 'sowhat.so')
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/python/java.py b/tests/python/java.py
index 81a93c1..3e331b4 100755
--- a/tests/python/java.py
+++ b/tests/python/java.py
@@ -2,6 +2,7 @@
import os
import unittest
+from test_helpers import BindingsTestCase
try:
import _satyr as satyr
@@ -18,7 +19,7 @@ if not os.path.isfile(path):
with file(path) as f:
contents = f.read()
-class TestJavaStacktrace(unittest.TestCase):
+class TestJavaStacktrace(BindingsTestCase):
def setUp(self):
self.trace = satyr.JavaStacktrace(contents)
@@ -49,15 +50,18 @@ class TestJavaStacktrace(unittest.TestCase):
out = str(self.trace)
self.assertTrue(('Java stacktrace with %d threads' % threads_expected) in out)
-class TestJavaThread(unittest.TestCase):
+class TestJavaThread(BindingsTestCase):
def setUp(self):
self.thread = satyr.JavaStacktrace(contents).threads[0]
-class TestJavaSharedlib(unittest.TestCase):
+ def test_getset(self):
+ self.assertGetSetCorrect(self.thread, 'name', None, 'elvis')
+
+class TestJavaSharedlib(BindingsTestCase):
def setUp(self):
self.shlib = satyr.JavaStacktrace(contents).libs[0]
-class TestJavaFrame(unittest.TestCase):
+class TestJavaFrame(BindingsTestCase):
def setUp(self):
self.frame = satyr.JavaStacktrace(contents).threads[0].frames[0]
@@ -69,20 +73,32 @@ class TestJavaFrame(unittest.TestCase):
def test_dup(self):
dup = self.frame.dup()
- self.assertEqual(dup.get_name(),
- self.frame.get_name())
+ self.assertEqual(dup.name,
+ self.frame.name)
- dup.set_name('other')
- self.assertNotEqual(dup.get_name(),
- self.frame.get_name())
+ dup.name = 'other'
+ self.assertNotEqual(dup.name,
+ self.frame.name)
def test_cmp(self):
dup = self.frame.dup()
self.assertEqual(dup.cmp(dup), 0)
self.assertEqual(dup.cmp(self.frame), 0)
self.assertEqual(dup.cmp(self.frame), 0)
- dup.set_name('another')
+ dup.name = 'another'
self.assertNotEqual(dup.cmp(self.frame), 0)
+ def test_getset(self):
+ self.assertGetSetCorrect(self.frame, 'name', 'org.hibernate.exception.ConstraintViolationException', 'long.name.is.Long')
+ self.assertGetSetCorrect(self.frame, 'file_name', None, 'java.java')
+ self.assertGetSetCorrect(self.frame, 'file_line', 0, 1234)
+ self.assertGetSetCorrect(self.frame, 'class_path', None, '/path/to/class')
+ self.assertGetSetCorrect(self.frame, 'is_exception', True, False)
+ ## not bool, expected to fail
+ #self.assertGetSetCorrect(self.frame, 'is_exception', False, 1)
+ self.assertGetSetCorrect(self.frame, 'is_native', False, True)
+ self.assertGetSetCorrect(self.frame, 'message', 'could not insert: [com.example.myproject.MyEntity]', 'printer on fire')
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/python/koops.py b/tests/python/koops.py
index 34292d4..fbeb8dd 100755
--- a/tests/python/koops.py
+++ b/tests/python/koops.py
@@ -2,6 +2,7 @@
import os
import unittest
+from test_helpers import BindingsTestCase
try:
import _satyr as satyr
@@ -18,7 +19,7 @@ if not os.path.isfile(path):
with file(path) as f:
contents = f.read()
-class TestKerneloops(unittest.TestCase):
+class TestKerneloops(BindingsTestCase):
def setUp(self):
self.koops = satyr.Kerneloops(contents)
@@ -26,7 +27,10 @@ class TestKerneloops(unittest.TestCase):
self.assertEqual(len(self.koops.frames), frames_expected)
def test_correct_modules(self):
- self.assertEqual(len(self.koops.get_modules()), mods_expected)
+ self.assertEqual(len(self.koops.modules), mods_expected)
+ ## not implemented, expected to fail
+ #self.koops.modules = ['foo', 'bar']
+ #self.assertEqual(len(self.koops.modules), 2)
def test_dup(self):
dup = self.koops.dup()
@@ -46,7 +50,7 @@ class TestKerneloops(unittest.TestCase):
out = str(self.koops)
self.assertTrue(('Kerneloops with %d frames' % frames_expected) in out)
-class TestKoopsFrame(unittest.TestCase):
+class TestKoopsFrame(BindingsTestCase):
def setUp(self):
self.frame = satyr.Kerneloops(contents).frames[0]
@@ -59,20 +63,33 @@ class TestKoopsFrame(unittest.TestCase):
def test_dup(self):
dup = self.frame.dup()
- self.assertEqual(dup.get_function_name(),
- self.frame.get_function_name())
+ self.assertEqual(dup.function_name,
+ self.frame.function_name)
- dup.set_function_name('other')
- self.assertNotEqual(dup.get_function_name(),
- self.frame.get_function_name())
+ dup.function_name = 'other'
+ self.assertNotEqual(dup.function_name,
+ self.frame.function_name)
def test_cmp(self):
dup = self.frame.dup()
self.assertEqual(dup.cmp(dup), 0)
self.assertEqual(dup.cmp(self.frame), 0)
self.assertEqual(dup.cmp(self.frame), 0)
- dup.set_reliable(False)
+ dup.reliable = False
self.assertNotEqual(dup.cmp(self.frame), 0)
+ def test_getset(self):
+ self.assertGetSetCorrect(self.frame, 'reliable', True, False)
+ self.assertGetSetCorrect(self.frame, 'address', 0xffffffff81057adfL, 60200)
+ self.assertGetSetCorrect(self.frame, 'function_name', 'warn_slowpath_common', 'fun_ction')
+ self.assertGetSetCorrect(self.frame, 'function_offset', 0x7f, 890)
+ self.assertGetSetCorrect(self.frame, 'function_length', 0xc0, 234)
+ self.assertGetSetCorrect(self.frame, 'module_name', None, 'dev_one.ko')
+ self.assertGetSetCorrect(self.frame, 'from_address', 0, 333333)
+ self.assertGetSetCorrect(self.frame, 'from_function_name', None, 'teh_caller')
+ self.assertGetSetCorrect(self.frame, 'from_function_offset', 0, 0x31337)
+ self.assertGetSetCorrect(self.frame, 'from_function_length', 0, 1024)
+ self.assertGetSetCorrect(self.frame, 'from_module_name', None, 'asdf')
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/python/python.py b/tests/python/python.py
index 5ef2975..59d61ce 100755
--- a/tests/python/python.py
+++ b/tests/python/python.py
@@ -3,6 +3,8 @@
import os
import unittest
+from test_helpers import BindingsTestCase
+
try:
import _satyr as satyr
except ImportError:
@@ -17,7 +19,7 @@ if not os.path.isfile(path):
with file(path) as f:
contents = f.read()
-class TestPythonStacktrace(unittest.TestCase):
+class TestPythonStacktrace(BindingsTestCase):
def setUp(self):
self.trace = satyr.PythonStacktrace(contents)
@@ -45,7 +47,12 @@ class TestPythonStacktrace(unittest.TestCase):
out = str(self.trace)
self.assertTrue(('Python stacktrace with %d frames' % frames_expected) in out)
-class TestPythonFrame(unittest.TestCase):
+ def test_getset(self):
+ self.assertGetSetCorrect(self.trace, 'file_name', None, 'moo.py')
+ self.assertGetSetCorrect(self.trace, 'file_line', 0, 42)
+ self.assertGetSetCorrect(self.trace, 'exception_name', 'AttributeError', 'WhateverException')
+
+class TestPythonFrame(BindingsTestCase):
def setUp(self):
self.frame = satyr.PythonStacktrace(contents).frames[0]
@@ -57,20 +64,27 @@ class TestPythonFrame(unittest.TestCase):
def test_dup(self):
dup = self.frame.dup()
- self.assertEqual(dup.get_function_name(),
- self.frame.get_function_name())
+ self.assertEqual(dup.function_name,
+ self.frame.function_name)
- dup.set_function_name('other')
- self.assertNotEqual(dup.get_function_name(),
- self.frame.get_function_name())
+ dup.function_name = 'other'
+ self.assertNotEqual(dup.function_name,
+ self.frame.function_name)
def test_cmp(self):
dup = self.frame.dup()
self.assertEqual(dup.cmp(dup), 0)
self.assertEqual(dup.cmp(self.frame), 0)
self.assertEqual(dup.cmp(self.frame), 0)
- dup.set_function_name('another')
+ dup.function_name = 'another'
self.assertNotEqual(dup.cmp(self.frame), 0)
+ def test_getset(self):
+ self.assertGetSetCorrect(self.frame, 'file_name', '/usr/share/PackageKit/helpers/yum/yumBackend.py', 'java.py')
+ self.assertGetSetCorrect(self.frame, 'file_line', 1830, 6667)
+ self.assertGetSetCorrect(self.frame, 'is_module', False, True)
+ self.assertGetSetCorrect(self.frame, 'function_name', '_runYumTransaction', 'iiiiii')
+ self.assertGetSetCorrect(self.frame, 'line_contents', 'rpmDisplay=rpmDisplay)', 'abcde')
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/python/test_helpers.py b/tests/python/test_helpers.py
new file mode 100644
index 0000000..4bd03a0
--- /dev/null
+++ b/tests/python/test_helpers.py
@@ -0,0 +1,14 @@
+import unittest
+
+class BindingsTestCase(unittest.TestCase):
+ def assertGetSetCorrect(self, obj, attr, orig_val, new_val):
+ '''
+ Check whether getting/setting an attribute works correctly.
+ '''
+ self.assertEqual(obj.__getattribute__(attr), orig_val)
+ obj.__setattr__(attr, new_val)
+ self.assertEqual(obj.__getattribute__(attr), new_val)
+
+if __name__ == '__main__':
+ import sys
+ sys.exit('This module is not meant to be run directly')
--
1.7.11.7
10 years, 12 months
[SATYR PATCH 1/4] Get rid of uninitialized warning in json.c
by Jakub Filak
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
lib/json.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/json.c b/lib/json.c
index f97e315..ddea4de 100644
--- a/lib/json.c
+++ b/lib/json.c
@@ -198,8 +198,8 @@ sr_json_parse_ex(struct sr_json_settings *settings,
{
json_uchar uchar;
unsigned char uc_b1, uc_b2, uc_b3, uc_b4;
- char *string;
- unsigned string_length;
+ char *string = NULL;
+ unsigned string_length = 0;
top = root = 0;
flags = flag_seek_value;
--
1.8.1.4
10 years, 12 months
[BTPARSER PATCH] Try harder when looking for crash thread
by Martin Milata
The current algorithm cannot handle backtraces with multiple threads
containing the designated crash frame such as [1]. We just pick the
shortest one with the risk that our guess might be wrong. Fixes #3.
[1] https://bugzilla.redhat.com/attachment.cgi?id=703269
Signed-off-by: Martin Milata <mmilata(a)redhat.com>
---
lib/backtrace.c | 45 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 34 insertions(+), 11 deletions(-)
diff --git a/lib/backtrace.c b/lib/backtrace.c
index a871eee..11050f8 100644
--- a/lib/backtrace.c
+++ b/lib/backtrace.c
@@ -117,27 +117,31 @@ btp_backtrace_remove_threads_except_one(struct btp_backtrace *backtrace,
backtrace->threads = thread;
}
+enum requirement { ONE_MATCHING, ABORT_FUNCTION, SHORTEST_MATCHING };
/**
* Loop through all threads and if a single one contains the crash
* frame on the top, return it. Otherwise, return NULL.
*
- * If require_abort is true, it is also required that the thread
- * containing the crash frame contains some known "abort" function. In
- * this case there can be multiple threads with the crash frame on the
- * top, but only one of them might contain the abort function to
- * succeed.
+ * Parameter req controlls the criteria for matching thread:
+ * ONE_MATCHING - There is only one thread that contains the crash frame.
+ * ABORT_FUNCTION - There may be multiple threads containing the crash frame
+ * but only one contains some known "abort" function.
+ * SHORTEST_MATCHING - If everything else fails, we just return the shortest
+ * thread containing the crash frame.
*/
static struct btp_thread *
btp_backtrace_find_crash_thread_from_crash_frame(struct btp_backtrace *backtrace,
- bool require_abort)
+ enum requirement req)
{
if (btp_debug_parser)
- printf("%s(backtrace, %s)\n", __FUNCTION__, require_abort ? "true" : "false");
+ printf("%s(backtrace, %s)\n", __FUNCTION__,
+ (req == ABORT_FUNCTION) ? "true" : "false");
assert(backtrace->threads); /* checked by the caller */
if (!backtrace->crash || !backtrace->crash->function_name)
return NULL;
+ int result_frames;
struct btp_thread *result = NULL;
struct btp_thread *thread = backtrace->threads;
while (thread)
@@ -146,7 +150,7 @@ btp_backtrace_find_crash_thread_from_crash_frame(struct btp_backtrace *backtrace
bool same_name = top_frame &&
top_frame->function_name &&
0 == strcmp(top_frame->function_name, backtrace->crash->function_name);
- bool abort_requirement_satisfied = !require_abort ||
+ bool abort_requirement_satisfied = (req != ABORT_FUNCTION) ||
btp_glibc_thread_find_exit_frame(thread);
if (btp_debug_parser)
{
@@ -158,13 +162,24 @@ btp_backtrace_find_crash_thread_from_crash_frame(struct btp_backtrace *backtrace
if (same_name && abort_requirement_satisfied)
{
+ int current_frames = btp_thread_get_frame_count(thread);
+
if (NULL == result)
+ {
result = thread;
- else
+ result_frames = current_frames;
+ }
+ else if (req != SHORTEST_MATCHING)
{
/* Second frame with the same function. Failure. */
return NULL;
}
+ else if (current_frames < result_frames)
+ {
+ /* We're just looking for the shortest frame that matches. */
+ result = thread;
+ result_frames = current_frames;
+ }
}
thread = thread->next;
@@ -188,7 +203,7 @@ btp_backtrace_find_crash_thread(struct btp_backtrace *backtrace)
* this frame on the top, it is also simple.
*/
struct btp_thread *thread;
- thread = btp_backtrace_find_crash_thread_from_crash_frame(backtrace, false);
+ thread = btp_backtrace_find_crash_thread_from_crash_frame(backtrace, ONE_MATCHING);
if (thread)
return thread;
@@ -196,7 +211,15 @@ btp_backtrace_find_crash_thread(struct btp_backtrace *backtrace)
* the crash frame on the top of stack.
* Try to search for known abort functions.
*/
- thread = btp_backtrace_find_crash_thread_from_crash_frame(backtrace, true);
+ thread = btp_backtrace_find_crash_thread_from_crash_frame(backtrace, ABORT_FUNCTION);
+ if (thread)
+ return thread;
+
+ /* There are multiple threads with the same crash frame and none of them
+ * contains known abort function.
+ * Take a guess and return the shortest one.
+ */
+ thread = btp_backtrace_find_crash_thread_from_crash_frame(backtrace, SHORTEST_MATCHING);
/* We might want to search a thread with known abort function, and
* without the crash frame here. However, it hasn't been needed so
--
1.7.11.7
11 years