Signed-off-by: Martin Milata mmilata@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, };