[SATYR PATCH 5/9] Add additional methods to thread

Martin Milata mmilata at redhat.com
Wed Jun 26 20:14:09 UTC 2013


Signed-off-by: Martin Milata <mmilata at redhat.com>
---
 include/frame.h          |  3 ++
 include/thread.h         | 37 ++++++++++++++++++++++
 lib/core_frame.c         |  1 +
 lib/core_stacktrace.c    |  2 +-
 lib/core_thread.c        |  6 ++++
 lib/gdb_frame.c          |  1 +
 lib/gdb_stacktrace.c     |  2 +-
 lib/gdb_thread.c         |  6 ++++
 lib/generic_frame.c      |  8 +++++
 lib/generic_frame.h      |  2 ++
 lib/generic_stacktrace.c |  5 ++-
 lib/generic_stacktrace.h |  4 +--
 lib/generic_thread.c     | 82 ++++++++++++++++++++++++++++++++++++++++++++++++
 lib/generic_thread.h     | 22 +++++++++++++
 lib/java_frame.c         |  1 +
 lib/java_stacktrace.c    |  2 +-
 lib/java_thread.c        |  6 ++++
 lib/koops_frame.c        |  1 +
 lib/koops_stacktrace.c   |  7 ++++-
 lib/python_frame.c       |  1 +
 lib/python_stacktrace.c  |  7 ++++-
 21 files changed, 198 insertions(+), 8 deletions(-)

diff --git a/include/frame.h b/include/frame.h
index 706522a..db8ea98 100644
--- a/include/frame.h
+++ b/include/frame.h
@@ -77,6 +77,9 @@ sr_frame_cmp(struct sr_frame *t1, struct sr_frame *t2);
 int
 sr_frame_cmp_distance(struct sr_frame *t1, struct sr_frame *t2);
 
+void
+sr_frame_free(struct sr_frame *frame);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/thread.h b/include/thread.h
index 1f39c2a..56bf1b5 100644
--- a/include/thread.h
+++ b/include/thread.h
@@ -37,6 +37,8 @@
 extern "C" {
 #endif
 
+#include <stdbool.h>
+
 #include "report_type.h"
 
 struct sr_thread
@@ -81,6 +83,41 @@ sr_thread_next(struct sr_thread *thread);
 void
 sr_thread_set_next(struct sr_thread *cur, struct sr_thread *next);
 
+/**
+ * Releases the memory held by the thread. The thread siblings are not
+ * released.
+ * @param thread
+ * If thread is NULL, no operation is performed.
+ */
+void
+sr_thread_free(struct sr_thread *thread);
+
+/**
+ * Removes the frame from the thread and then deletes it.
+ * @returns
+ * True if the frame was found in the thread and removed and deleted.
+ * False if the frame was not found in the thread.
+ */
+bool
+sr_thread_remove_frame(struct sr_thread *thread, struct sr_frame *frame);
+
+/**
+ * Removes all the frames from the thread that are above certain
+ * frame.
+ * @returns
+ * True if the frame was found, and all the frames that were above the
+ * frame in the thread were removed from the thread and then deleted.
+ * False if the frame was not found in the thread.
+ */
+bool
+sr_thread_remove_frames_above(struct sr_thread *thread, struct sr_frame *frame);
+
+/**
+ * Return a copy of the thread (without its siblings).
+ */
+struct sr_thread *
+sr_thread_dup(struct sr_thread *thread);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/lib/core_frame.c b/lib/core_frame.c
index 2833b8a..4ae8e8c 100644
--- a/lib/core_frame.c
+++ b/lib/core_frame.c
@@ -44,6 +44,7 @@ struct frame_methods core_frame_methods =
     .cmp_distance = (frame_cmp_fn_t) sr_core_frame_cmp_distance,
     .frame_append_bthash_text =
         (frame_append_bthash_text_fn_t) core_append_bthash_text,
+    .frame_free = (frame_free_fn_t) sr_core_frame_free,
 };
 
 /* Public functions */
diff --git a/lib/core_stacktrace.c b/lib/core_stacktrace.c
index 2b5997c..ff34221 100644
--- a/lib/core_stacktrace.c
+++ b/lib/core_stacktrace.c
@@ -59,7 +59,7 @@ struct stacktrace_methods core_stacktrace_methods =
         (find_crash_thread_fn_t) sr_core_stacktrace_find_crash_thread,
     .threads = (threads_fn_t) core_threads,
     .set_threads = (set_threads_fn_t) core_set_threads,
-    .free = (free_fn_t) sr_core_stacktrace_free,
+    .stacktrace_free = (stacktrace_free_fn_t) sr_core_stacktrace_free,
     .stacktrace_append_bthash_text =
         (stacktrace_append_bthash_text_fn_t) core_append_bthash_text,
 };
diff --git a/lib/core_thread.c b/lib/core_thread.c
index 5844ce9..d6e62b2 100644
--- a/lib/core_thread.c
+++ b/lib/core_thread.c
@@ -33,6 +33,7 @@ DEFINE_FRAMES_FUNC(core_frames, struct sr_core_thread)
 DEFINE_SET_FRAMES_FUNC(core_set_frames, struct sr_core_thread)
 DEFINE_NEXT_FUNC(core_next, struct sr_thread, struct sr_core_thread)
 DEFINE_SET_NEXT_FUNC(core_set_next, struct sr_thread, struct sr_core_thread)
+DEFINE_DUP_WRAPPER_FUNC(core_dup, struct sr_core_thread, sr_core_thread_dup)
 
 struct thread_methods core_thread_methods =
 {
@@ -44,6 +45,11 @@ struct thread_methods core_thread_methods =
     .set_next = (set_next_thread_fn_t) core_set_next,
     .thread_append_bthash_text =
         (thread_append_bthash_text_fn_t) thread_no_bthash_text,
+    .thread_free = (thread_free_fn_t) sr_core_thread_free,
+    .remove_frame = (remove_frame_fn_t) thread_remove_frame,
+    .remove_frames_above =
+        (remove_frames_above_fn_t) thread_remove_frames_above,
+    .thread_dup = (thread_dup_fn_t) core_dup,
 };
 
 /* Public functions */
diff --git a/lib/gdb_frame.c b/lib/gdb_frame.c
index 46acd4d..6deb1a3 100644
--- a/lib/gdb_frame.c
+++ b/lib/gdb_frame.c
@@ -54,6 +54,7 @@ struct frame_methods gdb_frame_methods =
     .cmp_distance = (frame_cmp_fn_t) sr_gdb_frame_cmp_distance,
     .frame_append_bthash_text =
         (frame_append_bthash_text_fn_t) gdb_append_bthash_text,
+    .frame_free = (frame_free_fn_t) sr_gdb_frame_free,
 };
 
 /* Public functions */
diff --git a/lib/gdb_stacktrace.c b/lib/gdb_stacktrace.c
index 6ccebab..9950c69 100644
--- a/lib/gdb_stacktrace.c
+++ b/lib/gdb_stacktrace.c
@@ -60,7 +60,7 @@ struct stacktrace_methods gdb_stacktrace_methods =
         (find_crash_thread_fn_t) sr_gdb_stacktrace_find_crash_thread,
     .threads = (threads_fn_t) gdb_threads,
     .set_threads = (set_threads_fn_t) gdb_set_threads,
-    .free = (free_fn_t) sr_gdb_stacktrace_free,
+    .stacktrace_free = (stacktrace_free_fn_t) sr_gdb_stacktrace_free,
     .stacktrace_append_bthash_text =
         (stacktrace_append_bthash_text_fn_t) gdb_append_bthash_text,
 };
diff --git a/lib/gdb_thread.c b/lib/gdb_thread.c
index 45da010..dc34320 100644
--- a/lib/gdb_thread.c
+++ b/lib/gdb_thread.c
@@ -41,6 +41,7 @@ DEFINE_FRAMES_FUNC(gdb_frames, struct sr_gdb_thread)
 DEFINE_SET_FRAMES_FUNC(gdb_set_frames, struct sr_gdb_thread)
 DEFINE_NEXT_FUNC(gdb_next, struct sr_thread, struct sr_gdb_thread)
 DEFINE_SET_NEXT_FUNC(gdb_set_next, struct sr_thread, struct sr_gdb_thread)
+DEFINE_DUP_WRAPPER_FUNC(gdb_dup, struct sr_gdb_thread, sr_gdb_thread_dup)
 
 struct thread_methods gdb_thread_methods =
 {
@@ -52,6 +53,11 @@ struct thread_methods gdb_thread_methods =
     .set_next = (set_next_thread_fn_t) gdb_set_next,
     .thread_append_bthash_text =
         (thread_append_bthash_text_fn_t) gdb_append_bthash_text,
+    .thread_free = (thread_free_fn_t) sr_gdb_thread_free,
+    .remove_frame = (remove_frame_fn_t) thread_remove_frame,
+    .remove_frames_above =
+        (remove_frames_above_fn_t) thread_remove_frames_above,
+    .thread_dup = (thread_dup_fn_t) gdb_dup,
 };
 
 /* Public functions */
diff --git a/lib/generic_frame.c b/lib/generic_frame.c
index 04a8407..b3a5f3c 100644
--- a/lib/generic_frame.c
+++ b/lib/generic_frame.c
@@ -79,3 +79,11 @@ frame_append_bthash_text(struct sr_frame *frame, enum sr_bthash_flags flags,
     DISPATCH(dtable, frame->type, frame_append_bthash_text)
             (frame, flags, strbuf);
 }
+
+void sr_frame_free(struct sr_frame *frame)
+{
+    if (!frame)
+        return;
+
+    DISPATCH(dtable, frame->type, frame_free)(frame);
+}
diff --git a/lib/generic_frame.h b/lib/generic_frame.h
index 69f1fa8..7a02bbe 100644
--- a/lib/generic_frame.h
+++ b/lib/generic_frame.h
@@ -30,6 +30,7 @@ typedef void (*set_next_frame_fn_t)(struct sr_frame *, struct sr_frame *);
 typedef int (*frame_cmp_fn_t)(struct sr_frame *, struct sr_frame *);
 typedef void (*frame_append_bthash_text_fn_t)(struct sr_frame*, enum sr_bthash_flags,
                                               struct sr_strbuf*);
+typedef void (*frame_free_fn_t)(struct sr_frame*);
 
 struct frame_methods
 {
@@ -39,6 +40,7 @@ struct frame_methods
     frame_cmp_fn_t cmp;
     frame_cmp_fn_t cmp_distance;
     frame_append_bthash_text_fn_t frame_append_bthash_text;
+    frame_free_fn_t frame_free;
 };
 
 extern struct frame_methods core_frame_methods, python_frame_methods,
diff --git a/lib/generic_stacktrace.c b/lib/generic_stacktrace.c
index bba7f5f..de393e4 100644
--- a/lib/generic_stacktrace.c
+++ b/lib/generic_stacktrace.c
@@ -138,7 +138,10 @@ sr_stacktrace_set_threads(struct sr_stacktrace *stacktrace, struct sr_thread *th
 void
 sr_stacktrace_free(struct sr_stacktrace *stacktrace)
 {
-    DISPATCH(dtable, stacktrace->type, free)(stacktrace);
+    if (!stacktrace)
+        return;
+
+    DISPATCH(dtable, stacktrace->type, stacktrace_free)(stacktrace);
 }
 
 char *
diff --git a/lib/generic_stacktrace.h b/lib/generic_stacktrace.h
index 829b680..f08bdfc 100644
--- a/lib/generic_stacktrace.h
+++ b/lib/generic_stacktrace.h
@@ -32,7 +32,7 @@ typedef char* (*get_reason_fn_t)(struct sr_stacktrace *);
 typedef struct sr_thread* (*find_crash_thread_fn_t)(struct sr_stacktrace *);
 typedef struct sr_thread* (*threads_fn_t)(struct sr_stacktrace *);
 typedef void (*set_threads_fn_t)(struct sr_stacktrace *, struct sr_thread *);
-typedef void (*free_fn_t)(struct sr_stacktrace *);
+typedef void (*stacktrace_free_fn_t)(struct sr_stacktrace *);
 typedef void (*stacktrace_append_bthash_text_fn_t)(struct sr_stacktrace *, enum sr_bthash_flags,
                                                    struct sr_strbuf *);
 
@@ -46,7 +46,7 @@ struct stacktrace_methods
     find_crash_thread_fn_t find_crash_thread;
     threads_fn_t threads;
     set_threads_fn_t set_threads;
-    free_fn_t free;
+    stacktrace_free_fn_t stacktrace_free;
     stacktrace_append_bthash_text_fn_t stacktrace_append_bthash_text;
 };
 
diff --git a/lib/generic_thread.c b/lib/generic_thread.c
index b0b3861..c9ff98a 100644
--- a/lib/generic_thread.c
+++ b/lib/generic_thread.c
@@ -45,6 +45,59 @@ thread_frame_count(struct sr_thread *thread)
     return count;
 }
 
+bool
+thread_remove_frame(struct sr_thread *thread, struct sr_frame *frame)
+{
+    struct sr_frame *loop_frame = sr_thread_frames(thread),
+        *prev_frame = NULL;
+
+    while (loop_frame)
+    {
+        if (loop_frame == frame)
+        {
+            if (prev_frame)
+                sr_frame_set_next(prev_frame, sr_frame_next(loop_frame));
+            else
+                sr_thread_set_frames(thread, sr_frame_next(loop_frame));
+
+            sr_frame_free(loop_frame);
+            return true;
+        }
+
+        prev_frame = loop_frame;
+        loop_frame = sr_frame_next(loop_frame);
+    }
+
+    return false;
+}
+
+bool
+thread_remove_frames_above(struct sr_thread *thread, struct sr_frame *frame)
+{
+    /* Check that the frame is present in the thread. */
+    struct sr_frame *loop_frame = sr_thread_frames(thread);
+    while (loop_frame)
+    {
+        if (loop_frame == frame)
+            break;
+
+        loop_frame = sr_frame_next(loop_frame);
+    }
+
+    if (!loop_frame)
+        return false;
+
+    /* Delete all the frames up to the frame. */
+    while (sr_thread_frames(thread) != frame)
+    {
+        loop_frame = sr_frame_next(sr_thread_frames(thread));
+        sr_frame_free(sr_thread_frames(thread));
+        sr_thread_set_frames(thread, loop_frame);
+    }
+
+    return true;
+}
+
 struct sr_thread *
 thread_no_next_thread(struct sr_thread *thread)
 {
@@ -119,3 +172,32 @@ thread_append_bthash_text(struct sr_thread *thread, enum sr_bthash_flags flags,
     DISPATCH(dtable, thread->type, thread_append_bthash_text)
             (thread, flags, strbuf);
 }
+
+void
+sr_thread_free(struct sr_thread *thread)
+{
+    if (!thread)
+        return;
+
+    DISPATCH(dtable, thread->type, thread_free)(thread);
+}
+
+bool
+sr_thread_remove_frame(struct sr_thread *thread, struct sr_frame *frame)
+{
+    assert(thread->type == frame->type);
+    return DISPATCH(dtable, thread->type, remove_frame)(thread, frame);
+}
+
+bool
+sr_thread_remove_frames_above(struct sr_thread *thread, struct sr_frame *frame)
+{
+    assert(thread->type == frame->type);
+    return DISPATCH(dtable, thread->type, remove_frames_above)(thread, frame);
+}
+
+struct sr_thread*
+sr_thread_dup(struct sr_thread *thread)
+{
+    return DISPATCH(dtable, thread->type, thread_dup)(thread);
+}
diff --git a/lib/generic_thread.h b/lib/generic_thread.h
index d3232d6..3914212 100644
--- a/lib/generic_thread.h
+++ b/lib/generic_thread.h
@@ -33,6 +33,10 @@ typedef struct sr_thread* (*next_thread_fn_t)(struct sr_thread*);
 typedef void (*set_next_thread_fn_t)(struct sr_thread*, struct sr_thread*);
 typedef void (*thread_append_bthash_text_fn_t)(struct sr_thread*, enum sr_bthash_flags,
                                                struct sr_strbuf*);
+typedef void (*thread_free_fn_t)(struct sr_thread*);
+typedef bool (*remove_frame_fn_t)(struct sr_thread*, struct sr_frame*);
+typedef bool (*remove_frames_above_fn_t)(struct sr_thread*, struct sr_frame*);
+typedef struct sr_thread* (*thread_dup_fn_t)(struct sr_thread*);
 
 struct thread_methods
 {
@@ -43,6 +47,10 @@ struct thread_methods
     next_thread_fn_t next;
     set_next_thread_fn_t set_next;
     thread_append_bthash_text_fn_t thread_append_bthash_text;
+    thread_free_fn_t thread_free;
+    remove_frame_fn_t remove_frame;
+    remove_frames_above_fn_t remove_frames_above;
+    thread_dup_fn_t thread_dup;
 };
 
 extern struct thread_methods core_thread_methods, python_thread_methods,
@@ -55,9 +63,23 @@ extern struct thread_methods core_thread_methods, python_thread_methods,
 #define DEFINE_SET_FRAMES_FUNC(name, concrete_t) \
     DEFINE_SETTER(name, frames, struct sr_thread, concrete_t, struct sr_frame)
 
+/* _dup wrapper for thread fucntions that accept 'sibling' argument */
+#define DEFINE_DUP_WRAPPER_FUNC(name, concrete_t, wrappee) \
+    static concrete_t *                                    \
+    name(concrete_t *thread)                               \
+    {                                                      \
+      return wrappee(thread, false);                       \
+    }
+
 int
 thread_frame_count(struct sr_thread *thread);
 
+bool
+thread_remove_frame(struct sr_thread *thread, struct sr_frame *frame);
+
+bool
+thread_remove_frames_above(struct sr_thread *thread, struct sr_frame *frame);
+
 struct sr_thread *
 thread_no_next_thread(struct sr_thread *thread);
 
diff --git a/lib/java_frame.c b/lib/java_frame.c
index 71881ca..4e61332 100644
--- a/lib/java_frame.c
+++ b/lib/java_frame.c
@@ -50,6 +50,7 @@ struct frame_methods java_frame_methods =
     .cmp_distance = (frame_cmp_fn_t) sr_java_frame_cmp_distance,
     .frame_append_bthash_text =
         (frame_append_bthash_text_fn_t) java_append_bthash_text,
+    .frame_free = (frame_free_fn_t) sr_java_frame_free,
 };
 
 /* Public functions */
diff --git a/lib/java_stacktrace.c b/lib/java_stacktrace.c
index d0b9152..f8ef874 100644
--- a/lib/java_stacktrace.c
+++ b/lib/java_stacktrace.c
@@ -53,7 +53,7 @@ struct stacktrace_methods java_stacktrace_methods =
         (find_crash_thread_fn_t) sr_java_find_crash_thread,
     .threads = (threads_fn_t) java_threads,
     .set_threads = (set_threads_fn_t) java_set_threads,
-    .free = (free_fn_t) sr_java_stacktrace_free,
+    .stacktrace_free = (stacktrace_free_fn_t) sr_java_stacktrace_free,
     .stacktrace_append_bthash_text =
         (stacktrace_append_bthash_text_fn_t) java_append_bthash_text,
 };
diff --git a/lib/java_thread.c b/lib/java_thread.c
index c3a697a..644ac34 100644
--- a/lib/java_thread.c
+++ b/lib/java_thread.c
@@ -41,6 +41,7 @@ DEFINE_FRAMES_FUNC(java_frames, struct sr_java_thread)
 DEFINE_SET_FRAMES_FUNC(java_set_frames, struct sr_java_thread)
 DEFINE_NEXT_FUNC(java_next, struct sr_thread, struct sr_java_thread)
 DEFINE_SET_NEXT_FUNC(java_set_next, struct sr_thread, struct sr_java_thread)
+DEFINE_DUP_WRAPPER_FUNC(java_dup, struct sr_java_thread, sr_java_thread_dup)
 
 struct thread_methods java_thread_methods =
 {
@@ -52,6 +53,11 @@ struct thread_methods java_thread_methods =
     .set_next = (set_next_thread_fn_t) java_set_next,
     .thread_append_bthash_text =
         (thread_append_bthash_text_fn_t) java_append_bthash_text,
+    .thread_free = (thread_free_fn_t) sr_java_thread_free,
+    .remove_frame = (remove_frame_fn_t) thread_remove_frame,
+    .remove_frames_above =
+        (remove_frames_above_fn_t) thread_remove_frames_above,
+    .thread_dup = (thread_dup_fn_t) java_dup,
 };
 
 /* Public functions */
diff --git a/lib/koops_frame.c b/lib/koops_frame.c
index 7ae3ece..aecd591 100644
--- a/lib/koops_frame.c
+++ b/lib/koops_frame.c
@@ -47,6 +47,7 @@ struct frame_methods koops_frame_methods =
     .cmp_distance = (frame_cmp_fn_t) sr_koops_frame_cmp_distance,
     .frame_append_bthash_text =
         (frame_append_bthash_text_fn_t) koops_append_bthash_text,
+    .frame_free = (frame_free_fn_t) sr_koops_frame_free,
 };
 
 /* Public functions */
diff --git a/lib/koops_stacktrace.c b/lib/koops_stacktrace.c
index 0533034..ab62598 100644
--- a/lib/koops_stacktrace.c
+++ b/lib/koops_stacktrace.c
@@ -73,6 +73,11 @@ struct thread_methods koops_thread_methods =
     .next = (next_thread_fn_t) thread_no_next_thread,
     .set_next = (set_next_thread_fn_t) NULL,
     .thread_append_bthash_text = (thread_append_bthash_text_fn_t) thread_no_bthash_text,
+    .thread_free = (thread_free_fn_t) sr_koops_stacktrace_free,
+    .remove_frame = (remove_frame_fn_t) thread_remove_frame,
+    .remove_frames_above =
+        (remove_frames_above_fn_t) thread_remove_frames_above,
+    .thread_dup = (thread_dup_fn_t) sr_koops_stacktrace_dup,
 };
 
 struct stacktrace_methods koops_stacktrace_methods =
@@ -85,7 +90,7 @@ struct stacktrace_methods koops_stacktrace_methods =
     .find_crash_thread = (find_crash_thread_fn_t) stacktrace_one_thread_only,
     .threads = (threads_fn_t) stacktrace_one_thread_only,
     .set_threads = (set_threads_fn_t) NULL,
-    .free = (free_fn_t) sr_koops_stacktrace_free,
+    .stacktrace_free = (stacktrace_free_fn_t) sr_koops_stacktrace_free,
     .stacktrace_append_bthash_text =
         (stacktrace_append_bthash_text_fn_t) koops_append_bthash_text,
 };
diff --git a/lib/python_frame.c b/lib/python_frame.c
index 8ac4b90..4a6a209 100644
--- a/lib/python_frame.c
+++ b/lib/python_frame.c
@@ -46,6 +46,7 @@ struct frame_methods python_frame_methods =
     .cmp_distance = (frame_cmp_fn_t) sr_python_frame_cmp_distance,
     .frame_append_bthash_text =
         (frame_append_bthash_text_fn_t) python_append_bthash_text,
+    .frame_free = (frame_free_fn_t) sr_python_frame_free,
 };
 
 /* Public functions */
diff --git a/lib/python_stacktrace.c b/lib/python_stacktrace.c
index 300bd0b..15bb41c 100644
--- a/lib/python_stacktrace.c
+++ b/lib/python_stacktrace.c
@@ -52,6 +52,11 @@ struct thread_methods python_thread_methods =
     .set_next = (set_next_thread_fn_t) NULL,
     .thread_append_bthash_text =
         (thread_append_bthash_text_fn_t) thread_no_bthash_text,
+    .thread_free = (thread_free_fn_t) sr_python_stacktrace_free,
+    .remove_frame = (remove_frame_fn_t) thread_remove_frame,
+    .remove_frames_above =
+        (remove_frames_above_fn_t) thread_remove_frames_above,
+    .thread_dup = (thread_dup_fn_t) sr_python_stacktrace_dup,
 };
 
 struct stacktrace_methods python_stacktrace_methods =
@@ -64,7 +69,7 @@ struct stacktrace_methods python_stacktrace_methods =
     .find_crash_thread = (find_crash_thread_fn_t) stacktrace_one_thread_only,
     .threads = (threads_fn_t) stacktrace_one_thread_only,
     .set_threads = (set_threads_fn_t) NULL,
-    .free = (free_fn_t) sr_python_stacktrace_free,
+    .stacktrace_free = (stacktrace_free_fn_t) sr_python_stacktrace_free,
     .stacktrace_append_bthash_text =
         (stacktrace_append_bthash_text_fn_t) python_append_bthash_text,
 };
-- 
1.7.11.7



More information about the Crash-catcher mailing list