Signed-off-by: Jakub Filak jfilak@redhat.com --- src/include/internal_libreport.h | 4 + src/lib/make_descr.c | 43 ++++++--- src/plugins/reporter-bugzilla.c | 2 +- src/plugins/rhbz.c | 200 ++++++++++++++++++++++++++++++++++---- 4 files changed, 215 insertions(+), 34 deletions(-)
diff --git a/src/include/internal_libreport.h b/src/include/internal_libreport.h index c57bd5f..23a74f9 100644 --- a/src/include/internal_libreport.h +++ b/src/include/internal_libreport.h @@ -581,6 +581,8 @@ enum { }; #define make_description libreport_make_description char *make_description(problem_data_t *problem_data, char **names_to_skip, unsigned max_text_size, unsigned desc_flags); +#define make_description_item_multiline libreport_make_description_item_multiline +char *make_description_item_multiline(const char *name, const char* content); #define make_description_bz libreport_make_description_bz char* make_description_bz(problem_data_t *problem_data, unsigned max_text_size); #define make_description_logger libreport_make_description_logger @@ -716,6 +718,8 @@ struct dump_dir *steal_directory(const char *base_dir, const char *dump_dir_name #define FILENAME_PKG_VERSION "pkg_version" #define FILENAME_PKG_RELEASE "pkg_release" #define FILENAME_PKG_ARCH "pkg_arch" +#define FILENAME_USERNAME "username" +#define FILENAME_ABRT_VERSION "abrt_version"
// Not stored as files, added "on the fly": #define CD_DUMPDIR "Directory" diff --git a/src/lib/make_descr.c b/src/lib/make_descr.c index 68133a2..21fb83c 100644 --- a/src/lib/make_descr.c +++ b/src/lib/make_descr.c @@ -26,6 +26,27 @@ static bool rejected_name(const char *name, char **v, int flags) return r; }
+char *make_description_item_multiline(const char *name, const char *content) +{ + char *eol = strchr(content, '\n'); + if (!eol) + return NULL; + + struct strbuf *buf = strbuf_new(); + strbuf_append_str(buf, name); + strbuf_append_str(buf, ":\n"); + for (;;) + { + eol = strchrnul(content, '\n'); + strbuf_append_strf(buf, ":%.*s\n", (int)(eol - content), content); + if (*eol == '\0' || eol[1] == '\0') + break; + content = eol + 1; + } + + return strbuf_free_nobuf(buf); +} + char *make_description(problem_data_t *problem_data, char **names_to_skip, unsigned max_text_size, unsigned desc_flags) { @@ -171,24 +192,18 @@ char *make_description(problem_data_t *problem_data, char **names_to_skip, || (!strcmp(analyzer, "Kerneloops") && !strcmp(key, FILENAME_BACKTRACE)))) { char *formatted = format_problem_item(item); - char *output = formatted ? formatted : item->content; - char *eol = strchr(output, '\n'); - if (eol) + char *output = make_description_item_multiline(key, formatted ? formatted : item->content); + + if (output) { if (!empty) - strbuf_append_char(buf_dsc, '\n'); - strbuf_append_str(buf_dsc, key); - strbuf_append_str(buf_dsc, ":\n"); - for (;;) - { - eol = strchrnul(output, '\n'); - strbuf_append_strf(buf_dsc, ":%.*s\n", (int)(eol - output), output); - if (*eol == '\0' || eol[1] == '\0') - break; - output = eol + 1; - } + strbuf_append_str(buf_dsc, "\n"); + + strbuf_append_str(buf_dsc, output); empty = false; + free(output); } + free(formatted); } } diff --git a/src/plugins/reporter-bugzilla.c b/src/plugins/reporter-bugzilla.c index b96549d..bb59ac7 100644 --- a/src/plugins/reporter-bugzilla.c +++ b/src/plugins/reporter-bugzilla.c @@ -349,7 +349,7 @@ int main(int argc, char **argv) int flags = RHBZ_NOMAIL_NOTIFY; if (opts & OPT_b) flags |= RHBZ_ATTACH_BINARY_FILES; - rhbz_attach_big_files(client, bug_id_str, problem_data, flags); + rhbz_attach_files(client, bug_id_str, problem_data, flags);
bz = new_bug_info(); bz->bi_status = xstrdup("NEW"); diff --git a/src/plugins/rhbz.c b/src/plugins/rhbz.c index 53662e1..1eca5d4 100644 --- a/src/plugins/rhbz.c +++ b/src/plugins/rhbz.c @@ -19,6 +19,11 @@
#include "internal_libreport.h" #include "rhbz.h" +#include <btparser/location.h> +#include <btparser/backtrace.h> +#include <btparser/thread.h> +#include <btparser/frame.h> +#include <btparser/strbuf.h>
#define MAX_HOPS 5
@@ -32,6 +37,78 @@ #define func_entry_str(x) #endif
+/******************************************************************************/ +/* Global lists used in process of creation a new Bugzilla bug + * New bug logic: + * 1. 'Description of problem' is FILENAME_COMMENT + * 2. 'Version-Release number of selected component' is FILENAME_PACKAGE + * 3. 'Additional info' is a concatenation of files listed in ADDITIONAL_INFO_FILES_LIST + * 3.1 backtrace is also present in 'Additional info' + * - if has size lower than CD_TEXT_ATT_SIZE_BZ then the bactrace is inlined + * - otherwise preview of crashed thread stack trace is created + * 4. Attached files are the ONLY files which ARE NOT present in g_not_attached_files + * As you can see g_not_attached_files consist from some hardcoded files and + * files from ADDITIONAL_INFO_FILES_LIST. + * Black list for attached files allows us to attach all of files added to + * a problem directory by a user. + */ +#define INLINED_FILES_LIST\ + FILENAME_ABRT_VERSION,\ + FILENAME_RATING,\ + FILENAME_KERNEL,\ + FILENAME_CRASH_FUNCTION,\ + FILENAME_CMDLINE,\ + FILENAME_TAINTED_LONG + +/* Items we want to use in additional info */ +static const char *const g_additional_info_files[] = { + /* ! a bunch of file names */ + INLINED_FILES_LIST, + NULL +}; + +/* Items we don't want to attach to bz */ +static const char *const g_not_attached_files[] = { + CD_DUMPDIR, + FILENAME_ANALYZER, + FILENAME_PID, + FILENAME_PWD, + FILENAME_ROOTDIR, + FILENAME_BINARY, + FILENAME_COREDUMP, + FILENAME_DUPHASH, + FILENAME_ARCHITECTURE, + FILENAME_OS_RELEASE, + FILENAME_OS_RELEASE_IN_ROOTDIR, + FILENAME_PACKAGE, + FILENAME_COMPONENT, + FILENAME_COMMENT, + FILENAME_HOSTNAME, + FILENAME_REASON, + FILENAME_UID, + FILENAME_REMOTE, + FILENAME_TAINTED, + FILENAME_TAINTED_SHORT, + FILENAME_VMCORE, + FILENAME_UUID, + FILENAME_COUNT, + FILENAME_REPORTED_TO, + FILENAME_NOT_REPORTABLE, + FILENAME_PKG_EPOCH, + FILENAME_PKG_NAME, + FILENAME_PKG_VERSION, + FILENAME_PKG_RELEASE, + FILENAME_PKG_ARCH, + FILENAME_REMOTE_RESULT, + FILENAME_USERNAME, + FILENAME_TIME, + FILENAME_EXECUTABLE, + /* ! a bunch of file names */ + INLINED_FILES_LIST, + NULL +}; +/******************************************************************************/ + struct bug_info *new_bug_info() { func_entry(); @@ -461,6 +538,61 @@ struct bug_info *rhbz_bug_info(struct abrt_xmlrpc *ax, int bug_id) return bz; }
+/* + * Produces an optimal backtrace for bugzilla comment + */ +char *rhbz_get_backtrace_info(problem_data_t *problem_data, size_t max_text_size) +{ + const problem_item *item = get_problem_data_item_or_NULL(problem_data, + FILENAME_BACKTRACE); + + if (!item) + return NULL; + + char *truncated = NULL; + + if (strlen(item->content) >= max_text_size) + { + struct btp_location location; + btp_location_init(&location); + + /* btp_backtrace_parse modifies the input parameter */ + char *content = item->content; + struct btp_backtrace *backtrace = btp_backtrace_parse((const char **)&content, &location); + + if (!backtrace) + { + log(_("Can't parse backtrace")); + return NULL; + } + + /* Get optimized thread stack trace for 10 top most frames */ + struct btp_thread *thread = btp_backtrace_get_optimized_thread(backtrace, 10); + if (!thread) + { + btp_backtrace_free(backtrace); + log(_("Can't find crash thread")); + return NULL; + } + + /* Cannot be NULL, it dies on memory error */ + struct btp_strbuf *bt = btp_strbuf_new(); + + for (struct btp_frame *frame = thread->frames; frame; frame=frame->next) + btp_frame_append_to_str(frame, bt, true); + + btp_backtrace_free(backtrace); + + truncated = btp_strbuf_free_nobuf(bt); + } + + char *bt = make_description_item_multiline(truncated ? "truncated backtrace" : FILENAME_BACKTRACE, + truncated ? truncated : item->content); + free(truncated); + + return bt; +} + /* suppress mail notify by {s:i} (nomail:1) (driven by flag) */ int rhbz_new_bug(struct abrt_xmlrpc *ax, problem_data_t *problem_data, const char *release) @@ -520,14 +652,39 @@ int rhbz_new_bug(struct abrt_xmlrpc *ax, problem_data_t *problem_data, } char *status_whiteboard = xasprintf("abrt_hash:%s", duphash);
- char *bz_dsc; + char *full_dsc = NULL; if (analyzer && !strcmp(analyzer, "Kerneloops")) - bz_dsc = make_description_koops(problem_data, CD_TEXT_ATT_SIZE_BZ); + { + char *bz_dsc = make_description_koops(problem_data, CD_TEXT_ATT_SIZE_BZ); + full_dsc = xasprintf("libreport version: "VERSION"\n%s", bz_dsc); + free(bz_dsc); + } else - bz_dsc = make_description_bz(problem_data, CD_TEXT_ATT_SIZE_BZ); - - char *full_dsc = xasprintf("libreport version: "VERSION"\n%s", bz_dsc); - free(bz_dsc); + { + const char *comment = get_problem_item_content_or_NULL(problem_data, + FILENAME_COMMENT); + + char *bz_dsc = make_description(problem_data, (char**)g_additional_info_files, + CD_TEXT_ATT_SIZE_BZ, MAKEDESC_SHOW_MULTILINE | MAKEDESC_WHITELIST); + + char *backtrace = rhbz_get_backtrace_info(problem_data, CD_TEXT_ATT_SIZE_BZ); + + /* Generating of a description according to the RH bugzilla default format: + * https://bugzilla.redhat.com/enter_bug.cgi?product=Fedora + */ + full_dsc = xasprintf("Description of problem:\n%s\n\n" + "Version-Release number of selected component:\n%s\n\n" + "Additional info:\n" + "libreport version: "VERSION"\n%s\n" + "%s", + comment ? comment : "", + package, + bz_dsc, + backtrace ? backtrace : ""); + + free(backtrace); + free(bz_dsc); + }
char *product = NULL; char *version = NULL; @@ -631,7 +788,7 @@ int rhbz_attach_fd(struct abrt_xmlrpc *ax, const char *filename, }
/* suppress mail notify by {s:i} (nomail:1) (driven by flag) */ -int rhbz_attach_big_files(struct abrt_xmlrpc *ax, const char *bug_id, +int rhbz_attach_files(struct abrt_xmlrpc *ax, const char *bug_id, problem_data_t *problem_data, int flags) { func_entry(); @@ -643,26 +800,31 @@ int rhbz_attach_big_files(struct abrt_xmlrpc *ax, const char *bug_id, const char *analyzer = get_problem_item_content_or_NULL(problem_data, FILENAME_ANALYZER);
+ const bool kerneloops = !strcmp(analyzer, "Kerneloops"); + g_hash_table_iter_init(&iter, problem_data); while (g_hash_table_iter_next(&iter, (void**)&name, (void**)&value)) { + /* The not attached list is used only if analyzer is not Kerneloops. + * + * For standard bugs: + * The not attached list contains files that are used in the description or + * in the bug fields and the files which nobody is interested in. + */ + if (!kerneloops && is_in_string_list(name, (char**)g_not_attached_files)) + continue; + if (value->flags & CD_FLAG_TXT) { const char *content = value->content; - if (!strcmp(analyzer, "Kerneloops") && !strcmp(name, FILENAME_BACKTRACE)) - continue; + const unsigned len = strlen(content);
- unsigned len = strlen(content); + /* Do not attach backtrace in case of Kerneloops */ + /* For standard bugs, do not attach backtrace shorter than CD_TEXT_ATT_SIZE_BZ */ + if (!strcmp(name, FILENAME_BACKTRACE) && (kerneloops || len < CD_TEXT_ATT_SIZE_BZ)) + continue;
- // We were special-casing FILENAME_BACKTRACE here, but karel says - // he can retrieve it in inlined form from comments too. - if (len > CD_TEXT_ATT_SIZE_BZ /*|| (strcmp(name, FILENAME_BACKTRACE) == 0)*/) - { - /* This text item wasn't added in comments, it is too big - * for that. Attach it as a file. - */ - rhbz_attach_blob(ax, name, bug_id, content, len, flags); - } + rhbz_attach_blob(ax, name, bug_id, content, len, flags); } if ((flags & RHBZ_ATTACH_BINARY_FILES) && (value->flags & CD_FLAG_BIN)) {
crash-catcher@lists.fedorahosted.org