summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2011-03-15 10:12:32 +0100
committerDenys Vlasenko <dvlasenk@redhat.com>2011-03-15 10:12:32 +0100
commit7e0fb81d0e7fb98f94285fb2c3a5fae961a32a00 (patch)
tree92077af1d48664dafcd18363778e2c5e38d21c77
parentc3295e8741d5f35e30301933bd853bf6c9369588 (diff)
downloadabrt-7e0fb81d0e7fb98f94285fb2c3a5fae961a32a00.tar.gz
abrt-7e0fb81d0e7fb98f94285fb2c3a5fae961a32a00.tar.xz
abrt-7e0fb81d0e7fb98f94285fb2c3a5fae961a32a00.zip
gui-wizard-gtk: save event processing log
Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
-rw-r--r--src/gui-wizard-gtk/wizard.c113
-rw-r--r--src/include/abrt_crash_data.h26
2 files changed, 122 insertions, 17 deletions
diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c
index 6b58739e..d0a9c080 100644
--- a/src/gui-wizard-gtk/wizard.c
+++ b/src/gui-wizard-gtk/wizard.c
@@ -588,9 +588,17 @@ struct analyze_event_data
GtkTextView *tv_log;
const char *end_msg;
GIOChannel *channel;
+ struct strbuf *event_log;
+ int event_log_state;
int fd;
/*guint event_source_id;*/
};
+enum {
+ LOGSTATE_FIRSTLINE = 0,
+ LOGSTATE_BEGLINE,
+ LOGSTATE_ERRLINE,
+ LOGSTATE_MIDLINE,
+};
static GList *export_event_config(const char *event_name)
{
@@ -638,31 +646,119 @@ static int spawn_next_command_in_evd(struct analyze_event_data *evd)
return r;
}
+static void save_to_event_log(struct analyze_event_data *evd, const char *str)
+{
+ static const char delim[] = {
+ [LOGSTATE_FIRSTLINE] = '>',
+ [LOGSTATE_BEGLINE] = ' ',
+ [LOGSTATE_ERRLINE] = '*',
+ };
+
+ while (str[0])
+ {
+ char *end = strchrnul(str, '\n');
+ char end_char = *end;
+ if (end_char == '\n')
+ end++;
+ switch (evd->event_log_state)
+ {
+ case LOGSTATE_FIRSTLINE:
+ case LOGSTATE_BEGLINE:
+ case LOGSTATE_ERRLINE:
+ /* skip empty lines */
+ if (str[0] == '\n')
+ goto next;
+ strbuf_append_strf(evd->event_log, "%s%c %.*s",
+ iso_date_string(NULL),
+ delim[evd->event_log_state],
+ (int)(end - str), str
+ );
+ break;
+ case LOGSTATE_MIDLINE:
+ strbuf_append_strf(evd->event_log, "%.*s", (int)(end - str), str);
+ break;
+ }
+ evd->event_log_state = LOGSTATE_MIDLINE;
+ if (end_char != '\n')
+ break;
+ evd->event_log_state = LOGSTATE_BEGLINE;
+ next:
+ str = end;
+ }
+}
+
+static void update_event_log_on_disk(const char *str)
+{
+ struct dump_dir *dd = dd_opendir(g_dump_dir_name, 0);
+ if (!dd)
+ return;
+ char *event_log = dd_load_text_ext(dd, FILENAME_EVENT_LOG, DD_FAIL_QUIETLY_ENOENT);
+
+ event_log = append_to_malloced_string(event_log, str);
+ char *new_log = event_log;
+ unsigned len = strlen(event_log);
+ if (len > EVENT_LOG_HIGH_WATERMARK)
+ {
+ new_log += len - EVENT_LOG_LOW_WATERMARK;
+ new_log = strchrnul(new_log, '\n');
+ if (new_log[0])
+ new_log++;
+ }
+
+ dd_save_text(dd, FILENAME_EVENT_LOG, new_log);
+ free(event_log);
+ dd_close(dd);
+}
+
static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, gpointer data)
{
struct analyze_event_data *evd = data;
/* Read and insert the output into the log pane */
- char buf[256]; /* usually we get one line, no need to have big buf */
+ char buf[257]; /* usually we get one line, no need to have big buf */
int r;
- while ((r = read(evd->fd, buf, sizeof(buf))) > 0)
+ while ((r = read(evd->fd, buf, sizeof(buf)-1)) > 0)
{
+ buf[r] = '\0';
append_to_textview(evd->tv_log, buf, r);
+ save_to_event_log(evd, buf);
}
if (r < 0 && errno == EAGAIN)
/* We got all buffered data, but fd is still open. Done for now */
return TRUE; /* "please don't remove this event (yet)" */
- /* EOF/error. Wait for child to actually exit, collect status */
+ /* EOF/error */
+
+ unexport_event_config(evd->env_list);
+ evd->env_list = NULL;
+
+ /* Wait for child to actually exit, collect status */
int status;
waitpid(evd->run_state->command_pid, &status, 0);
int retval = WEXITSTATUS(status);
if (WIFSIGNALED(status))
retval = WTERMSIG(status) + 128;
- unexport_event_config(evd->env_list);
- evd->env_list = NULL;
+ /* Write a final message to the log */
+ if (evd->event_log->len != 0 && evd->event_log->buf[evd->event_log->len - 1] != '\n')
+ save_to_event_log(evd, "\n");
+ if (retval != 0)
+ {
+ evd->event_log_state = LOGSTATE_ERRLINE;
+ char *msg;
+ if (WIFSIGNALED(status))
+ msg = xasprintf("(killed by signal %d)\n", WTERMSIG(status));
+ else
+ msg = xasprintf("(exited with %d)\n", retval);
+ save_to_event_log(evd, msg);
+ free(msg);
+ }
+
+ /* Append log to FILENAME_EVENT_LOG */
+ update_event_log_on_disk(evd->event_log->buf);
+ strbuf_clear(evd->event_log);
+ evd->event_log_state = LOGSTATE_FIRSTLINE;
/* Stop if exit code is not 0, or no more commands */
if (retval != 0
@@ -684,6 +780,7 @@ static gboolean consume_cmd_output(GIOChannel *source, GIOCondition condition, g
/*g_source_remove(evd->event_source_id);*/
close(evd->fd);
free_run_event_state(evd->run_state);
+ strbuf_free(evd->event_log);
free(evd);
reload_crash_data_from_dump_dir();
@@ -776,6 +873,7 @@ static void start_event_run(const char *event_name,
evd->status_label = status_label;
evd->tv_log = tv_log;
evd->end_msg = end_msg;
+ evd->event_log = strbuf_new();
evd->fd = state->command_out_fd;
ndelay_on(evd->fd);
evd->channel = g_io_channel_unix_new(evd->fd);
@@ -786,7 +884,7 @@ static void start_event_run(const char *event_name,
);
gtk_label_set_text(status_label, start_msg);
- /* Freeze assistant so it can't move away from the page until analyzing is done */
+ /* Freeze assistant so it can't move away from the page until event run is done */
gtk_assistant_set_page_complete(g_assistant, page, false);
}
@@ -914,7 +1012,8 @@ static void next_page(GtkAssistant *assistant, gpointer user_data)
for (GList *li = reporters; li; li = li->next)
{
if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(li->data)) == TRUE)
- li->data = (gpointer)gtk_button_get_label(GTK_BUTTON(li->data));
+ /* Button's tooltip contains event_name */
+ li->data = (gpointer)gtk_widget_get_tooltip_text(GTK_WIDGET(li->data));
else
li->data = NULL;
}
diff --git a/src/include/abrt_crash_data.h b/src/include/abrt_crash_data.h
index 3abd408c..5a03f397 100644
--- a/src/include/abrt_crash_data.h
+++ b/src/include/abrt_crash_data.h
@@ -25,15 +25,15 @@
// Text bigger than this usually is attached, not added inline
#define CD_TEXT_ATT_SIZE (2*1024)
-// Keep in sync with CCDump.py:
-
// Filenames in dump directory:
// filled by a hook:
+#define FILENAME_REASON "reason" /* mandatory */
+#define FILENAME_UID "uid" /* mandatory */
+#define FILENAME_TIME "time" /* mandatory */
#define FILENAME_ANALYZER "analyzer"
#define FILENAME_EXECUTABLE "executable"
#define FILENAME_BINARY "binary"
#define FILENAME_CMDLINE "cmdline"
-#define FILENAME_REASON "reason"
#define FILENAME_COREDUMP "coredump"
#define FILENAME_BACKTRACE "backtrace"
#define FILENAME_MAPS "maps"
@@ -45,8 +45,7 @@
// filled by CDebugDump::Create() (which also fills FILENAME_UID):
#define FILENAME_ARCHITECTURE "architecture"
#define FILENAME_KERNEL "kernel"
-#define FILENAME_TIME "time"
-// From /etc/syste-release or /etc/redhat-release
+// From /etc/system-release or /etc/redhat-release
#define FILENAME_OS_RELEASE "os_release"
// Filled by <what?>
#define FILENAME_PACKAGE "package"
@@ -59,17 +58,24 @@
#define FILENAME_TAINTED "kernel_tainted"
// TODO: TicketUploader also has open-coded "TICKET", "CUSTOMER" files
-#define FILENAME_UID "uid"
-#define FILENAME_UUID "uuid"
-#define FILENAME_INFORMALL "inform_all_users"
-#define FILENAME_COUNT "count"
-#define FILENAME_MESSAGE "message"
+#define FILENAME_UUID "uuid"
+#define FILENAME_INFORMALL "inform_all_users"
+#define FILENAME_COUNT "count"
+#define FILENAME_MESSAGE "message"
+#define FILENAME_EVENT_LOG "event_log"
// Not stored as files, added "on the fly":
#define CD_DUMPDIR "DumpDir"
// "Which events are possible (make sense) on this crash dump?"
// (a string with "\n" terminated event names)
#define CD_EVENTS "Events"
+/* FILENAME_EVENT_LOG is trimmed to below LOW_WATERMARK
+ * when it reaches HIGH_WATERMARK size
+ */
+enum {
+ EVENT_LOG_HIGH_WATERMARK = 30 * 1024,
+ EVENT_LOG_LOW_WATERMARK = 20 * 1024,
+};
#ifdef __cplusplus
extern "C" {