[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
10 years, 12 months
[FAF PATCH] bugzilla: use bthash for linking to problems
by Richard Marko
It's better to use hashes instead of IDs which might change, we have
support for this since 3000b1b.
Closes #170.
Signed-off-by: Richard Marko <rmarko(a)redhat.com>
---
config/templates/bugzilla_new_body | 2 +-
config/templates/bugzilla_update_comment | 2 +-
pyfaf/bugzilla.py | 16 +++++++++++++++-
tests/bugzilla | 4 ++--
4 files changed, 19 insertions(+), 5 deletions(-)
diff --git a/config/templates/bugzilla_new_body b/config/templates/bugzilla_new_body
index d6402eb..a4b01f5 100644
--- a/config/templates/bugzilla_new_body
+++ b/config/templates/bugzilla_new_body
@@ -3,7 +3,7 @@ Description of problem:
Faf server recevied number of crash reports for this package.
Problem URL:
-{{ server_url }}{% url pyfaf.hub.problems.views.item problem.id %}
+{{ server_url }}{% url pyfaf.hub.problems.views.bthash_forward faf_hash %}
Version-Release number of selected component:
{{ package.nvra }}
diff --git a/config/templates/bugzilla_update_comment b/config/templates/bugzilla_update_comment
index 6a1cc6a..c86b2af 100644
--- a/config/templates/bugzilla_update_comment
+++ b/config/templates/bugzilla_update_comment
@@ -2,6 +2,6 @@
This problem received over {{report_count}} reports.
{% if server_url %}
Following link might provide more details:
-{{ server_url }}{% url pyfaf.hub.problems.views.item problem.id %}
+{{ server_url }}{% url pyfaf.hub.problems.views.bthash_forward faf_hash %}
{% endif %}
{% endautoescape %}
diff --git a/pyfaf/bugzilla.py b/pyfaf/bugzilla.py
index 4b374d2..4c3a84c 100644
--- a/pyfaf/bugzilla.py
+++ b/pyfaf/bugzilla.py
@@ -743,6 +743,7 @@ class Bugzilla(object):
data['executable'] = report.executables[0].path
data['duphash'] = report.backtraces[0].btp_hash()
+ data['faf_hash'] = report.backtraces[0].hash
highest_version = -1
highest_release = None
@@ -901,9 +902,22 @@ class Bugzilla(object):
new_wb = '{0} reports:{1}'.format(bug.whiteboard,
current_count)
+ # get top report
+ if not problem.reports:
+ logging.warning('Refusing to process problem with no reports.')
+ continue
+
+ report = problem.sorted_reports[0]
+ if not report.backtraces:
+ logging.warning('Refusing to process report with no backtrace.')
+ continue
+
+ faf_hash = report.backtraces[0].hash
+
comment = template.render(template_name,
dict(report_count=current_count,
- problem=problem))
+ problem=problem,
+ faf_hash=faf_hash))
logging.info('Adding comment to bug #{0}.'
' Comment:\n\n{1}\n'.format(bug.id, comment))
diff --git a/tests/bugzilla b/tests/bugzilla
index 8cc1fe2..fd6b1fe 100755
--- a/tests/bugzilla
+++ b/tests/bugzilla
@@ -291,7 +291,7 @@ class BugzillaTestCase(faftests.RealworldCase):
self.assertIn('in unknown function', bug['summary'])
self.assertIn('reports count', bug['description'])
- self.assertIn('https://example.org/problems/1/', bug['description'])
+ self.assertIn('https://example.org/problems/bthash/', bug['description'])
self.assertIn('server(a)example.org', bug['description'])
self.assertNotIn('None', bug['summary'])
@@ -390,7 +390,7 @@ class BugzillaTestCase(faftests.RealworldCase):
break
text = comment.get_lob('content')
- self.assertIn('https://example.org/problems/1/', text)
+ self.assertIn('https://example.org/problems/bthash/', text)
self.assertIn(str(prob.reports_count), text)
def test_update_bugs_doesnt_update_too_soon(self):
--
1.8.1.4
11 years
[FAF PATCH] bugzilla: pick report with highest count
by Richard Marko
When creating new ticket make sure we pick
report with highest count so we don't end up
linking to unrelated report if clustering
splits the problem.
Closes #172.
Signed-off-by: Richard Marko <rmarko(a)redhat.com>
---
pyfaf/bugzilla.py | 2 +-
pyfaf/storage/problem.py | 8 ++++++++
2 files changed, 9 insertions(+), 1 deletion(-)
diff --git a/pyfaf/bugzilla.py b/pyfaf/bugzilla.py
index 678a6d9..4b374d2 100644
--- a/pyfaf/bugzilla.py
+++ b/pyfaf/bugzilla.py
@@ -721,7 +721,7 @@ class Bugzilla(object):
logging.warning('Refusing to process problem with no reports.')
continue
- report = problem.reports[0]
+ report = problem.sorted_reports[0]
if not report.backtraces:
logging.warning('Refusing to process report with no backtrace.')
continue
diff --git a/pyfaf/storage/problem.py b/pyfaf/storage/problem.py
index 7242517..e8ee1a5 100644
--- a/pyfaf/storage/problem.py
+++ b/pyfaf/storage/problem.py
@@ -92,3 +92,11 @@ class Problem(GenericTable):
sorted by quality.
'''
return sorted(self.backtraces, key=lambda bt: bt.quality, reverse=True)
+
+ @property
+ def sorted_reports(self):
+ """
+ Return list of all reports sorted by report count.
+ """
+
+ return sorted(self.reports, key=lambda report: report.count, reverse=True)
--
1.8.1.4
11 years
[RHEL6 LIBREPORT PATCH 1/4] remove new line from ask/ask_password responses
by Denys Vlasenko
Signed-off-by: Denys Vlasenko <dvlasenk(a)redhat.com>
---
src/lib/client.c | 8 +++++++-
1 files changed, 7 insertions(+), 1 deletions(-)
diff --git a/src/lib/client.c b/src/lib/client.c
index 3dce30b..48e7f3c 100644
--- a/src/lib/client.c
+++ b/src/lib/client.c
@@ -78,7 +78,10 @@ char *ask(const char *question)
fflush(stdout);
- return xmalloc_fgets(stdin);
+ char *result = xmalloc_fgets(stdin);
+ strtrimch(result, '\n');
+
+ return result;
}
char *ask_password(const char *question)
@@ -91,7 +94,10 @@ char *ask_password(const char *question)
fflush(stdout);
bool changed = set_echo(false);
+
char *result = xmalloc_fgets(stdin);
+ strtrimch(result, '\n');
+
if (changed)
set_echo(true);
--
1.7.1
11 years
[PATCH] Fix crashes in drop identical oops frames when bt suffix contains only identical frames
by Jakub Filak
- closes #5
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
lib/core-backtrace-oops.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/core-backtrace-oops.c b/lib/core-backtrace-oops.c
index 672efa7..47a80f6 100644
--- a/lib/core-backtrace-oops.c
+++ b/lib/core-backtrace-oops.c
@@ -82,10 +82,10 @@ btp_drop_identical_frames(GList *kerneloops)
GList *result = kerneloops, *cur = kerneloops, *next;
for (next = g_list_next(cur); next; next = g_list_next(cur))
{
- while (btp_backtrace_entry_equal(cur->data, next->data))
+ if (btp_backtrace_entry_equal(cur->data, next->data))
{
result = g_list_remove(result, next->data);
- next = g_list_next(cur);
+ continue;
}
cur = next;
--
1.8.1.4
11 years
[SATYR PATCH] python: duplicate code refactorization, part 1
by Martin Milata
Hi,
this is an attempt to get rid of duplicate code in satyr python bindings. I
tried to reuse the code for a function that is currently repeated several
times. This is accomplished by treating all pointers that can have different
types as void* and accessing structure members through pointer arithmetic.
As a consequence it bypasses the type checking and thus is somewhat difficult
to debug. I'm starting to think that writing the function as a preprocessor
macro might be a better approach. I'll be grateful for any advice.
-->8-->8-->8-->8-->8-->8-->8-->8-->8-->8-->8-->8--
The code that performs C linked list reconstruction from python list
object was consolidated into single function which treats all pointers
as void* in order to work with different (yet structurally similar)
structures.
Signed-off-by: Martin Milata <mmilata(a)redhat.com>
---
python/Makefile.am | 2 +
python/py_common.c | 78 ++++++++++++++++++++++++++++++
python/py_common.h | 109 ++++++++++++++++++++++++++++++++++++++++++
python/py_gdb_stacktrace.c | 100 ++++++++++----------------------------
python/py_gdb_thread.c | 48 +++++--------------
python/py_java_stacktrace.c | 51 ++++----------------
python/py_java_thread.c | 47 ++++--------------
python/py_koops_stacktrace.c | 49 +++++--------------
python/py_python_stacktrace.c | 47 ++++--------------
tests/python/metrics.py | 9 ++++
10 files changed, 276 insertions(+), 264 deletions(-)
create mode 100644 python/py_common.c
create mode 100644 python/py_common.h
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..f35cfd4
--- /dev/null
+++ b/python/py_common.c
@@ -0,0 +1,78 @@
+/*
+ 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"
+
+int
+prepare_linked_list(void *owner, PyTypeObject *inferior_type, const char *owner_pylist_name,
+ size_t owner_pylist_off, size_t owner_payload_off, size_t payload_list_off,
+ size_t inferior_payload_off, size_t next_off)
+{
+ int i;
+ PyObject *item;
+ void *current = NULL, *prev = NULL;
+
+ /* XXX: check that MEMB(owner, owner_pylist_off) is indeed list */
+
+ for (i = 0; i < PyList_Size(MEMB(owner, owner_pylist_off)); ++i)
+ {
+ item = PyList_GetItem(MEMB(owner, owner_pylist_off), i);
+ if (!item)
+ return -1;
+
+ Py_INCREF(item);
+
+ if (!PyObject_TypeCheck(item, inferior_type))
+ {
+ char error_msg[256];
+ Py_XDECREF(item);
+ Py_XDECREF(prev);
+
+ PyOS_snprintf(error_msg, sizeof(error_msg), "%s must be a list of %s objects",
+ owner_pylist_name, inferior_type->tp_name);
+ PyErr_SetString(PyExc_TypeError, error_msg);
+ return -1;
+ }
+
+ current = item;
+ if (i == 0)
+ {
+ /* owner->owner_payload->payload_list = current->inferior_payload */
+ MEMB(MEMB(owner, owner_payload_off), payload_list_off)
+ = MEMB(current, inferior_payload_off);
+ }
+ else
+ /* prev->inferior_payload->next = current->inferior_payload */
+ MEMB(MEMB(prev, inferior_payload_off), next_off)
+ = MEMB(current, inferior_payload_off);
+
+ Py_XDECREF(prev);
+ prev = current;
+ }
+
+ if (current)
+ {
+ //current->inferior_c_struct->next = NULL;
+ MEMB(MEMB(current, inferior_payload_off), next_off) = NULL;
+ Py_DECREF(current);
+ }
+
+ return 0;
+}
diff --git a/python/py_common.h b/python/py_common.h
new file mode 100644
index 0000000..284b96c
--- /dev/null
+++ b/python/py_common.h
@@ -0,0 +1,109 @@
+/*
+ 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>
+
+/*
+ * MEMB(st, offsetof(typeof(st), member)) == (void*)(st->member)
+ */
+#define MEMB(st, off) *(void**)((char*)st + off)
+
+/**
+ * @brief Creates C linked list that can be used in a function from its python
+ * representation.
+ *
+ * Satyr uses linked lists heavily, and their python representation follows a
+ * common pattern. When a C structure contains a linked list, the python API
+ * exposes it as a python list. The python list contains references to
+ * individual elements and takes care of freeing them after no references point
+ * to them. When we need to call a C function on such object, we build a
+ * C-style linked list from the python list by updating the next pointers to
+ * reflect the ordering in the python list. This function does the updating.
+ * There are four kinds of objects involved:
+ *
+ * owner: Owner is the python object that wraps the satyr object and exposes
+ * the list contained in that satyr object as a python list. It contains
+ * reference to the C object (payload), and python list of the items contained
+ * in payload.
+ *
+ * inferior: Inferior is python object that wraps the individual elements in
+ * the list.
+ *
+ * payload: Payload is the C structure that is wrapped by the owner object.
+ * Inferior also wraps a python object, which we'll call inferior-payload.
+ *
+ * Take GDB thread as an example. In this context, struct sr_py_gdb_thread is
+ * the owner -- the main object we care about. It is a wrapper around struct
+ * sr_gdb_thread, which is the payload. Threads are sequences of frames and
+ * we'll refer to the python object containing a frame, struct sr_py_gdb_frame,
+ * as an inferior. And last, struct sr_gdb_frame, is the inferior-payload.
+ *
+ * @param owner The main python object for which we'll be reconstructing the
+ * linked list.
+ *
+ * @param inferior_type Pointer to the python type object of the inferiors.
+ * E.g. &sr_py_gdb_frame_type for GDB thread (note the &).
+ *
+ * @param owner_pylist_name Name of the attribute containing the python list.
+ * Used for error message.
+ *
+ * @param owner_pylist_off Offset of the python list in the owner structure.
+ * E.g. offsetof(struct sr_py_gdb_thread, frames) for GDB thread.
+ *
+ * @param owner_payload_off Offset of the payload in the owner structure.
+ * E.g. offsetof(struct sr_py_gdb_thread, thread) for GDB thread.
+ *
+ * @param payload_list_off Offset of the list pointer in the payload structure.
+ * E.g. offsetof(struct sr_gdb_thread, frames) for GDB thread.
+ *
+ * @param inferior_payload_off Offset of the payload pointer in the inferior
+ * python object. E.g. offsetof(struct sr_py_gdb_frame, frame) for GDB thread.
+ *
+ * @param next_off Offset of the next pointer in the inferior-payload C
+ * structure. E.g. offsetof(struct sr_gdb_frame, next) for GDB thread.
+ *
+ * @returns 0 on success, -1 on error
+ */
+int prepare_linked_list(void *owner,
+ PyTypeObject *inferior_type,
+ const char *owner_pylist_name,
+ size_t owner_pylist_off,
+ size_t owner_payload_off,
+ size_t payload_list_off,
+ size_t inferior_payload_off,
+ size_t next_off);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* SATYR_PY_COMMON_H */
diff --git a/python/py_gdb_stacktrace.c b/python/py_gdb_stacktrace.c
index f16965b..3126b38 100644
--- a/python/py_gdb_stacktrace.c
+++ b/python/py_gdb_stacktrace.c
@@ -2,6 +2,7 @@
#include "py_gdb_thread.h"
#include "py_gdb_frame.h"
#include "py_gdb_sharedlib.h"
+#include "py_common.h"
#include "lib/strbuf.h"
#include "lib/gdb_stacktrace.h"
#include "lib/gdb_thread.h"
@@ -155,81 +156,30 @@ PyTypeObject sr_py_gdb_stacktrace_type = {
int
stacktrace_prepare_linked_list(struct sr_py_gdb_stacktrace *stacktrace)
{
- int i;
- PyObject *item;
-
- /* thread */
- struct sr_py_gdb_thread *current = NULL, *prev = NULL;
- for (i = 0; i < PyList_Size(stacktrace->threads); ++i)
- {
- item = PyList_GetItem(stacktrace->threads, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
- if (!PyObject_TypeCheck(item, &sr_py_gdb_thread_type))
- {
- Py_XDECREF(current);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError,
- "threads must be a list of satyr.Thread objects");
- return -1;
- }
-
- current = (struct sr_py_gdb_thread*)item;
- if (thread_prepare_linked_list(current) < 0)
- return -1;
-
- if (i == 0)
- stacktrace->stacktrace->threads = current->thread;
- else
- prev->thread->next = current->thread;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->thread->next = NULL;
- Py_XDECREF(current);
- }
-
- /* sharedlib */
- struct sr_py_gdb_sharedlib *currentlib = NULL, *prevlib = NULL;
- for (i = 0; i < PyList_Size(stacktrace->libs); ++i)
- {
- item = PyList_GetItem(stacktrace->libs, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
- if (!PyObject_TypeCheck(item, &sr_py_gdb_sharedlib_type))
- {
- Py_XDECREF(currentlib);
- Py_XDECREF(prevlib);
- PyErr_SetString(PyExc_TypeError,
- "libs must be a list of satyr.Sharedlib objects");
- return -1;
- }
-
- currentlib = (struct sr_py_gdb_sharedlib*)item;
- if (i == 0)
- stacktrace->stacktrace->libs = currentlib->sharedlib;
- else
- prevlib->sharedlib->next = currentlib->sharedlib;
-
- Py_XDECREF(prevlib);
- prevlib = currentlib;
- }
-
- if (currentlib)
- {
- currentlib->sharedlib->next = NULL;
- Py_XDECREF(currentlib);
- }
-
- return 0;
+ int res = prepare_linked_list(
+ stacktrace,
+ &sr_py_gdb_thread_type,
+ "threads",
+ offsetof(struct sr_py_gdb_stacktrace, threads),
+ offsetof(struct sr_py_gdb_stacktrace, stacktrace),
+ offsetof(struct sr_gdb_stacktrace, threads),
+ offsetof(struct sr_py_gdb_thread, thread),
+ offsetof(struct sr_gdb_thread, next)
+ );
+
+ if (res < 0)
+ return res;
+
+ return prepare_linked_list(
+ stacktrace,
+ &sr_py_gdb_sharedlib_type,
+ "libs",
+ offsetof(struct sr_py_gdb_stacktrace, libs),
+ offsetof(struct sr_py_gdb_stacktrace, stacktrace),
+ offsetof(struct sr_gdb_stacktrace, libs),
+ offsetof(struct sr_py_gdb_sharedlib, sharedlib),
+ offsetof(struct sr_gdb_sharedlib, next)
+ );
}
int
diff --git a/python/py_gdb_thread.c b/python/py_gdb_thread.c
index c5098bb..bbbffc1 100644
--- a/python/py_gdb_thread.c
+++ b/python/py_gdb_thread.c
@@ -1,5 +1,6 @@
#include "py_gdb_thread.h"
#include "py_gdb_frame.h"
+#include "py_common.h"
#include "lib/strbuf.h"
#include "lib/gdb_thread.h"
#include "lib/gdb_frame.h"
@@ -121,43 +122,16 @@ PyTypeObject sr_py_gdb_thread_type =
int
thread_prepare_linked_list(struct sr_py_gdb_thread *thread)
{
- int i;
- PyObject *item;
- struct sr_py_gdb_frame *current = NULL, *prev = NULL;
-
- for (i = 0; i < PyList_Size(thread->frames); ++i)
- {
- item = PyList_GetItem(thread->frames, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
-
- if (!PyObject_TypeCheck(item, &sr_py_gdb_frame_type))
- {
- Py_XDECREF(item);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError, "frames must be a list of satyr.Frame objects");
- return -1;
- }
-
- current = (struct sr_py_gdb_frame*)item;
- if (i == 0)
- thread->thread->frames = current->frame;
- else
- prev->frame->next = current->frame;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->frame->next = NULL;
- Py_DECREF(current);
- }
-
- return 0;
+ return prepare_linked_list(
+ thread, /* owner */
+ &sr_py_gdb_frame_type, /*inferior_type*/
+ "frames", /* owner_pylist_name */
+ offsetof(struct sr_py_gdb_thread, frames), /* owner_pylist_off */
+ offsetof(struct sr_py_gdb_thread, thread), /* owner_payload_off */
+ offsetof(struct sr_gdb_thread, frames), /* payload_list_off */
+ offsetof(struct sr_py_gdb_frame, frame), /* inferior_payload_off */
+ offsetof(struct sr_gdb_frame, next) /* next_off */
+ );
}
int
diff --git a/python/py_java_stacktrace.c b/python/py_java_stacktrace.c
index ed91088..b15da77 100644
--- a/python/py_java_stacktrace.c
+++ b/python/py_java_stacktrace.c
@@ -92,47 +92,16 @@ PyTypeObject sr_py_java_stacktrace_type = {
int
java_stacktrace_prepare_linked_list(struct sr_py_java_stacktrace *stacktrace)
{
- int i;
- PyObject *item;
-
- /* thread */
- struct sr_py_java_thread *current = NULL, *prev = NULL;
- for (i = 0; i < PyList_Size(stacktrace->threads); ++i)
- {
- item = PyList_GetItem(stacktrace->threads, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
- if (!PyObject_TypeCheck(item, &sr_py_java_thread_type))
- {
- Py_XDECREF(current);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError,
- "threads must be a list of satyr.JavaThread objects");
- return -1;
- }
-
- current = (struct sr_py_java_thread*)item;
- if (java_thread_prepare_linked_list(current) < 0)
- return -1;
-
- if (i == 0)
- stacktrace->stacktrace->threads = current->thread;
- else
- prev->thread->next = current->thread;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->thread->next = NULL;
- Py_XDECREF(current);
- }
-
- return 0;
+ return prepare_linked_list(
+ stacktrace,
+ &sr_py_java_thread_type,
+ "threads",
+ offsetof(struct sr_py_java_stacktrace, threads),
+ offsetof(struct sr_py_java_stacktrace, stacktrace),
+ offsetof(struct sr_java_stacktrace, threads),
+ offsetof(struct sr_py_java_thread, thread),
+ offsetof(struct sr_java_thread, next)
+ );
}
int
diff --git a/python/py_java_thread.c b/python/py_java_thread.c
index 4416918..d15e8ba 100644
--- a/python/py_java_thread.c
+++ b/python/py_java_thread.c
@@ -122,43 +122,16 @@ PyTypeObject sr_py_java_thread_type =
int
java_thread_prepare_linked_list(struct sr_py_java_thread *thread)
{
- int i;
- PyObject *item;
- struct sr_py_java_frame *current = NULL, *prev = NULL;
-
- for (i = 0; i < PyList_Size(thread->frames); ++i)
- {
- item = PyList_GetItem(thread->frames, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
-
- if (!PyObject_TypeCheck(item, &sr_py_java_frame_type))
- {
- Py_XDECREF(item);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError, "frames must be a list of satyr.JavaFrame objects");
- return -1;
- }
-
- current = (struct sr_py_java_frame*)item;
- if (i == 0)
- thread->thread->frames = current->frame;
- else
- prev->frame->next = current->frame;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->frame->next = NULL;
- Py_DECREF(current);
- }
-
- return 0;
+ return prepare_linked_list(
+ thread,
+ &sr_py_java_frame_type,
+ "frames",
+ offsetof(struct sr_py_java_thread, frames),
+ offsetof(struct sr_py_java_thread, thread),
+ offsetof(struct sr_java_thread, frames),
+ offsetof(struct sr_py_java_frame, frame),
+ offsetof(struct sr_java_frame, next)
+ );
}
int
diff --git a/python/py_koops_stacktrace.c b/python/py_koops_stacktrace.c
index 345664e..9fe603a 100644
--- a/python/py_koops_stacktrace.c
+++ b/python/py_koops_stacktrace.c
@@ -1,5 +1,6 @@
#include "py_koops_frame.h"
#include "py_koops_stacktrace.h"
+#include "py_common.h"
#include "lib/strbuf.h"
#include "lib/koops_frame.h"
#include "lib/koops_stacktrace.h"
@@ -91,47 +92,21 @@ PyTypeObject sr_py_koops_stacktrace_type = {
NULL, /* tp_weaklist */
};
+
/* helpers */
int
koops_stacktrace_prepare_linked_list(struct sr_py_koops_stacktrace *stacktrace)
{
- int i;
- PyObject *item;
-
- struct sr_py_koops_frame *current = NULL, *prev = NULL;
- for (i = 0; i < PyList_Size(stacktrace->frames); ++i)
- {
- item = PyList_GetItem(stacktrace->frames, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
- if (!PyObject_TypeCheck(item, &sr_py_koops_frame_type))
- {
- Py_XDECREF(current);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError,
- "frames must be a list of satyr.KerneloopsFrame objects");
- return -1;
- }
-
- current = (struct sr_py_koops_frame*)item;
- if (i == 0)
- stacktrace->stacktrace->frames = current->frame;
- else
- prev->frame->next = current->frame;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->frame->next = NULL;
- Py_XDECREF(current);
- }
-
- return 0;
+ return prepare_linked_list(
+ stacktrace,
+ &sr_py_koops_frame_type,
+ "frames",
+ offsetof(struct sr_py_koops_stacktrace, frames),
+ offsetof(struct sr_py_koops_stacktrace, stacktrace),
+ offsetof(struct sr_koops_stacktrace, frames),
+ offsetof(struct sr_py_koops_frame, frame),
+ offsetof(struct sr_koops_frame, next)
+ );
}
PyObject *
diff --git a/python/py_python_stacktrace.c b/python/py_python_stacktrace.c
index 5ad3ac0..3e908ba 100644
--- a/python/py_python_stacktrace.c
+++ b/python/py_python_stacktrace.c
@@ -119,43 +119,16 @@ PyTypeObject sr_py_python_stacktrace_type = {
int
python_stacktrace_prepare_linked_list(struct sr_py_python_stacktrace *stacktrace)
{
- int i;
- PyObject *item;
-
- struct sr_py_python_frame *current = NULL, *prev = NULL;
- for (i = 0; i < PyList_Size(stacktrace->frames); ++i)
- {
- item = PyList_GetItem(stacktrace->frames, i);
- if (!item)
- return -1;
-
- Py_INCREF(item);
- if (!PyObject_TypeCheck(item, &sr_py_python_frame_type))
- {
- Py_XDECREF(current);
- Py_XDECREF(prev);
- PyErr_SetString(PyExc_TypeError,
- "frames must be a list of satyr.PythonFrame objects");
- return -1;
- }
-
- current = (struct sr_py_python_frame*)item;
- if (i == 0)
- stacktrace->stacktrace->frames = current->frame;
- else
- prev->frame->next = current->frame;
-
- Py_XDECREF(prev);
- prev = current;
- }
-
- if (current)
- {
- current->frame->next = NULL;
- Py_XDECREF(current);
- }
-
- return 0;
+ return prepare_linked_list(
+ stacktrace,
+ &sr_py_python_frame_type,
+ "frames",
+ offsetof(struct sr_py_python_stacktrace, frames),
+ offsetof(struct sr_py_python_stacktrace, stacktrace),
+ offsetof(struct sr_python_stacktrace, frames),
+ offsetof(struct sr_py_python_frame, frame),
+ offsetof(struct sr_python_frame, next)
+ );
}
PyObject *
diff --git a/tests/python/metrics.py b/tests/python/metrics.py
index a97e5eb..3d11920 100755
--- a/tests/python/metrics.py
+++ b/tests/python/metrics.py
@@ -43,5 +43,14 @@ class TestDistances(unittest.TestCase):
distances = satyr.Distances("levenshtein", [thread1, thread2], 2)
self.assertAlmostEqual(distances.get_distance(0, 1), 0.0)
+ # we should get a TypeError if we replace frames with garbage
+ thread1.frames = ['WAT?!!!']
+ self.assertRaises(TypeError, satyr.Distances, "levenshtein", [thread1, thread2], 2)
+
+ ## what if frames is not list?
+ #thread1.frames = 42
+ #thread2.frames = None
+ #distances = satyr.Distances("levenshtein", [thread1, thread2], 2)
+
if __name__ == '__main__':
unittest.main()
--
1.7.11.7
11 years
[FAF PATCH] do not prefix kernel module names with ~faf; closes #146
by Michal Toman
Signed-off-by: Michal Toman <mtoman(a)redhat.com>
---
pyfaf/ureport.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/pyfaf/ureport.py b/pyfaf/ureport.py
index bcc3f77..2a20d28 100644
--- a/pyfaf/ureport.py
+++ b/pyfaf/ureport.py
@@ -414,7 +414,8 @@ def add_report(ureport, db, utctime=None, count=1, only_check_if_known=False, re
if not "path" in frame and "executable" in ureport:
frame["path"] = ureport["executable"]
- frame["path"] = os.path.abspath(frame["path"])
+ if ureport["type"].lower() != "kerneloops":
+ frame["path"] = os.path.abspath(frame["path"])
hash_type, hash_hash = get_report_hash(ureport, component.name)
--
1.8.1.4
11 years
[FAF PATCH] bugzilla: strip function arguments when creating ticket
by Richard Marko
Long lists of arguments were causing ticket body to be too long.
Signed-off-by: Richard Marko <rmarko(a)redhat.com>
---
pyfaf/bugzilla.py | 11 +++++++++--
1 file changed, 9 insertions(+), 2 deletions(-)
diff --git a/pyfaf/bugzilla.py b/pyfaf/bugzilla.py
index 9f6a9f7..728f4fc 100644
--- a/pyfaf/bugzilla.py
+++ b/pyfaf/bugzilla.py
@@ -775,15 +775,22 @@ class Bugzilla(object):
our_frames = []
for position, frame in enumerate(frames):
more = ''
+ name = frame.name
+
+ # strip arguments in case of c++ function names containing
+ # long lists of them
+ if '(' in name:
+ name = name.split('(')[0]
+
if frame.source_path and frame.line_num:
more = '{0}:{1}'.format(frame.source_path, frame.line_num)
if report.type == 'PYTHON':
- our_frames.append((position, frame.name,
+ our_frames.append((position, name,
'{0}:{1}'.format(frame.source_path,
frame.line_num)))
else:
- our_frames.append((position, frame.name, frame.path, more))
+ our_frames.append((position, name, frame.path, more))
data['backtrace'] = pyfaf.support.as_table(
backtrace_header, our_frames,
--
1.8.1.4
11 years
[FAF PATCH] bugzilla: skip problems with kb entries
by Richard Marko
Signed-off-by: Richard Marko <rmarko(a)redhat.com>
---
pyfaf/bugzilla.py | 4 ++++
pyfaf/kb.py | 18 ++++++++++++++++++
2 files changed, 22 insertions(+)
diff --git a/pyfaf/bugzilla.py b/pyfaf/bugzilla.py
index e7b4503..16945e1 100644
--- a/pyfaf/bugzilla.py
+++ b/pyfaf/bugzilla.py
@@ -718,6 +718,10 @@ class Bugzilla(object):
logging.warning('Refusing to process report with no backtrace.')
continue
+ if pyfaf.kb.report_in_kb(self.db, report):
+ logging.info('Report matches knowledge base entry, skipping.')
+ continue
+
if report.packages:
data['package'] = report.packages[0].installed_package
if report.reasons:
diff --git a/pyfaf/kb.py b/pyfaf/kb.py
index 840f02e..18a5909 100644
--- a/pyfaf/kb.py
+++ b/pyfaf/kb.py
@@ -37,3 +37,21 @@ def get_kb_pkgname_parsers(db, opsys_id=None):
result[parser] = kbentry.solution
return result
+
+
+def report_in_kb(db, report):
+ '''
+ Check if `report` matches entry in knowledge base.
+ '''
+ if not report.backtraces:
+ return False
+
+ bt = report.backtraces[0]
+ parsers = get_kb_btpath_parsers(db)
+
+ for parser in parsers:
+ for frame in bt.frames:
+ if parser.match(frame.symbolsource.path):
+ return True
+
+ return False
--
1.8.1.4
11 years
[LIBREPORT PATCH] reporter-rhtsupport: fix hint query to use correct URL
by Denys Vlasenko
We should use rs/problems, not rs/cases/NNNNNNNN/problems.
To make similar bugs easier to spot in the future,
I added error message if we did get an error.
Signed-off-by: Denys Vlasenko <dvlasenk(a)redhat.com>
---
src/plugins/reporter-rhtsupport.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/src/plugins/reporter-rhtsupport.c b/src/plugins/reporter-rhtsupport.c
index 1183225..4a0d898 100644
--- a/src/plugins/reporter-rhtsupport.c
+++ b/src/plugins/reporter-rhtsupport.c
@@ -260,6 +260,8 @@ int main(int argc, char **argv)
);
free_map_string(settings);
+ char *base_api_url = xstrdup(url);
+
if (opts & OPT_t)
{
if (!case_no)
@@ -385,7 +387,7 @@ int main(int argc, char **argv)
{
/* Check for hints and show them if we have something */
log(_("Checking for hints"));
- result = get_rhts_hints(url,
+ result = get_rhts_hints(base_api_url,
login,
password,
ssl_verify,
@@ -408,6 +410,16 @@ int main(int argc, char **argv)
"</problems>"
);
#endif
+ if (result->error)
+ {
+ /* We don't use result->msg here because it looks like this:
+ * Error in file upload at 'URL', HTTP code: 404,
+ * server says: '<?xml...?><error...><code>404</code><message>...</message></error>'
+ * TODO: make server send bare textual msgs, not XML.
+ */
+ error_msg("Error in file upload at '%s', HTTP code: %d",
+ base_api_url, result->http_resp_code);
+ }
if (result->error == 0 && result->body)
{
/* The message might contain URLs to known solutions and such */
--
1.8.1.4
11 years