[PATCH] spawn_next_command: make process group creation optional
by Denys Vlasenko
spawn_next_command: make process group creation optional
Create process group only in wizard - where we originally
needed it.
he "sync" event running functions, OTOH, won't create
a new process group after this. This means that abrt-handle-event,
report-cli and similar CLI tools will not run events in a separate
process group and thus will be killable as a unit via ^C, SIGTERM etc.
Fixes libreport/issues/132.
--
vda
diff -x '*.po' -d -urpN libreport.6/src/gui-wizard-gtk/wizard.c libreport.7/src/gui-wizard-gtk/wizard.c
--- libreport.6/src/gui-wizard-gtk/wizard.c 2013-02-07 14:31:32.000000000 +0100
+++ libreport.7/src/gui-wizard-gtk/wizard.c 2013-02-13 14:10:20.234346678 +0100
@@ -1400,7 +1400,7 @@ static void set_excluded_envvar(void)
static int spawn_next_command_in_evd(struct analyze_event_data *evd)
{
evd->env_list = export_event_config(evd->event_name);
- int r = spawn_next_command(evd->run_state, g_dump_dir_name, evd->event_name);
+ int r = spawn_next_command(evd->run_state, g_dump_dir_name, evd->event_name, EXECFLG_SETPGID);
if (r >= 0)
{
g_event_child_pid = evd->run_state->command_pid;
@@ -1864,7 +1864,7 @@ static void start_event_run(const char *
set_excluded_envvar();
GList *env_list = export_event_config(event_name);
- if (spawn_next_command(state, g_dump_dir_name, event_name) < 0)
+ if (spawn_next_command(state, g_dump_dir_name, event_name, EXECFLG_SETPGID) < 0)
{
unexport_event_config(env_list);
goto no_cmds;
diff -x '*.po' -d -urpN libreport.6/src/include/run_event.h libreport.7/src/include/run_event.h
--- libreport.6/src/include/run_event.h 2013-02-07 14:31:32.000000000 +0100
+++ libreport.7/src/include/run_event.h 2013-02-13 14:13:09.530231446 +0100
@@ -143,10 +143,16 @@ void make_run_event_state_forwarding(str
/* Returns 0 if no commands found for this dump_dir_name+event, else >0 */
int prepare_commands(struct run_event_state *state, const char *dump_dir_name, const char *event);
-/* Returns -1 is no more commands needs to be executed,
- * else sets state->command_pid and state->command_out_fd and returns >=0
+/*
+ * Returns -1 if no more commands needs to be executed,
+ * else sets state->command_pid and state->command_out_fd and returns >=0.
+ * execflags can be e.g. EXECFLG_SETPGID to put the event handling process
+ * into a new process group, EXECFLG_SETSID to put it in a new session, etc.
*/
-int spawn_next_command(struct run_event_state *state, const char *dump_dir_name, const char *event);
+int spawn_next_command(struct run_event_state *state,
+ const char *dump_dir_name,
+ const char *event,
+ unsigned execflags);
/* Cleans up internal state created in prepare_commands */
void free_commands(struct run_event_state *state);
diff -x '*.po' -d -urpN libreport.6/src/lib/run_event.c libreport.7/src/lib/run_event.c
--- libreport.6/src/lib/run_event.c 2013-02-07 14:31:32.000000000 +0100
+++ libreport.7/src/lib/run_event.c 2013-02-13 14:14:22.436181525 +0100
@@ -110,7 +110,7 @@ void make_run_event_state_forwarding(str
* List of commands machinery is encapsulated in struct run_event_state,
* and public async API:
* prepare_commands(state, dir, event);
- * spawn_next_command(state, dir, event);
+ * spawn_next_command(state, dir, event, 0);
* free_commands(state);
* does not expose the way we select rules to execute.
*/
@@ -416,11 +416,12 @@ int prepare_commands(struct run_event_st
int spawn_next_command(struct run_event_state *state,
const char *dump_dir_name,
- const char *event
+ const char *event,
+ unsigned execflags
) {
char *cmd = pop_next_command(&state->rule_list,
NULL, /* don't return event_name */
- NULL, /* NULL &dd: we match by... */
+ NULL, /* NULL dd: we match by... */
dump_dir_name, /* ...dirname */
event, strlen(event)+1 /* for this event name exactly (not prefix) */
);
@@ -456,7 +457,7 @@ int spawn_next_command(struct run_event_
int pipefds[2];
state->command_pid = fork_execv_on_steroids(
- EXECFLG_INPUT + EXECFLG_OUTPUT + EXECFLG_ERR2OUT + EXECFLG_SETPGID,
+ EXECFLG_INPUT | EXECFLG_OUTPUT | EXECFLG_ERR2OUT | execflags,
argv,
pipefds,
/* env_vec: */ env_vec,
@@ -611,7 +612,7 @@ int run_event_on_dir_name(struct run_eve
/* Execute every command in shell */
int retval = 0;
- while (spawn_next_command(state, dump_dir_name, event) >= 0)
+ while (spawn_next_command(state, dump_dir_name, event, /*execflags:*/ 0) >= 0)
{
retval = consume_event_command_output(state, dump_dir_name);
if (retval != 0)
11 years, 2 months
[ABRT PATCH 1/2] retrace-client: print dots instead of repeated status message
by Jakub Filak
- related to #607
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/plugins/abrt-retrace-client.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/src/plugins/abrt-retrace-client.c b/src/plugins/abrt-retrace-client.c
index d06def4..1560ce6 100644
--- a/src/plugins/abrt-retrace-client.c
+++ b/src/plugins/abrt-retrace-client.c
@@ -20,6 +20,7 @@
#define MAX_FORMATS 16
#define MAX_RELEASES 32
+#define MAX_DOTS_PER_LINE 80
enum
{
@@ -1015,6 +1016,7 @@ static int run_batch(bool delete_temp_archive)
char *task_status = xstrdup("");
char *status_message = xstrdup("");
int status_delay = delay ? delay : 10;
+ int dots = 0;
while (0 != strncmp(task_status, "FINISHED", strlen("finished")))
{
char *previous_status_message = status_message;
@@ -1023,9 +1025,28 @@ static int run_batch(bool delete_temp_archive)
status(task_id, task_password, &task_status, &status_message);
if (g_verbose > 0 || 0 != strcmp(previous_status_message, status_message))
{
+ if (dots)
+ { /* A same message was received and a period was printed instead
+ * but the period wasn't followed by new line and now we are
+ * goning to print a new message thus we want to start at next line
+ */
+ dots = 0;
+ putchar('\n');
+ }
puts(status_message);
fflush(stdout);
}
+ else
+ {
+ if (dots >= MAX_DOTS_PER_LINE)
+ {
+ dots = 0;
+ putchar('\n');
+ }
+ ++dots;
+ client_log(".");
+ fflush(stdout);
+ }
free(previous_status_message);
previous_status_message = status_message;
}
--
1.8.1.2
11 years, 2 months
[ABRT PATCH] dbus: add basics to a new problem
by Jakub Filak
- related to #604
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/dbus/abrt-dbus.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/dbus/abrt-dbus.c b/src/dbus/abrt-dbus.c
index 754ef97..781bbe4 100644
--- a/src/dbus/abrt-dbus.c
+++ b/src/dbus/abrt-dbus.c
@@ -343,6 +343,9 @@ static char *handle_new_problem(GVariant *problem_info, uid_t caller_uid, char *
problem_data_add_text_noteditable(pd, FILENAME_UID, buf);
}
+ /* At least it should generate local problem identifier UUID */
+ problem_data_add_basics(pd);
+
char *problem_id = problem_data_save(pd);
if (!problem_id)
{
--
1.8.1.2
11 years, 2 months
[LIBREPORT PATCH] problem API: generate UUID if is missing instead of DUPHASH
by Jakub Filak
- closes #130
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/include/internal_libreport.h | 10 ++++++
src/lib/problem_data.c | 75 ++++++++++++++++++++++++----------------
2 files changed, 56 insertions(+), 29 deletions(-)
diff --git a/src/include/internal_libreport.h b/src/include/internal_libreport.h
index ed18c2d..1d40c00 100644
--- a/src/include/internal_libreport.h
+++ b/src/include/internal_libreport.h
@@ -718,7 +718,12 @@ struct dump_dir *open_directory_for_writing(
#define FILENAME_ENVIRON "environ"
#define FILENAME_LIMITS "limits"
#define FILENAME_OPEN_FDS "open_fds"
+
+/* Global problem identifier which is usually generated by some "analyze_*"
+ * event because it may take a lot of time to obtain strong problem
+ * identification */
#define FILENAME_DUPHASH "duphash"
+
// Name of the function where the application crashed.
// Optional.
#define FILENAME_CRASH_FUNCTION "crash_function"
@@ -744,7 +749,12 @@ struct dump_dir *open_directory_for_writing(
// The file should contain a description of an alert
#define FILENAME_DESCRIPTION "description"
+/* Local problem identifier (weaker than global identifier) designed for fast
+ * local for fast local duplicate identification. This file is usually provided
+ * by crashed application (problem creator).
+ */
#define FILENAME_UUID "uuid"
+
#define FILENAME_COUNT "count"
/* Multi-line list of places problem was reported.
* Recommended line format:
diff --git a/src/lib/problem_data.c b/src/lib/problem_data.c
index c3f240b..ac712e8 100644
--- a/src/lib/problem_data.c
+++ b/src/lib/problem_data.c
@@ -73,42 +73,59 @@ void problem_data_add_basics(problem_data_t *pd)
/* If application didn't provide dupe hash, we generate it
* from all components, so we at least eliminate the exact same
* reports
+ *
+ * We don't want to generate DUPHASH file because it is usually generated
+ * later in some "analyze_*" event. DUPHASH was originally designed as
+ * global problem identifier and generating of global identifier requires
+ * more space and data. On the contrary UUID was originally designed as
+ * local problem identifier. It means that this identifier is weaker (e.g.
+ * a hash generated from a coredump without debuginfo - there can be many
+ * similar backtraces without line numbers and function names).
*/
- if (problem_data_get_content_or_NULL(pd, FILENAME_DUPHASH) == NULL)
+ if (problem_data_get_content_or_NULL(pd, FILENAME_UUID) == NULL)
{
- /* start hash */
- sha1_ctx_t sha1ctx;
- sha1_begin(&sha1ctx);
-
- /*
- * To avoid spurious hash differences, sort keys so that elements are
- * always processed in the same order:
+ /* If application provided DUPHASH, we should use it in UUID as well.
+ * Otherwise we compute hash from all problem's data.
*/
- GList *list = g_hash_table_get_keys(pd);
- list = g_list_sort(list, (GCompareFunc)strcmp);
- GList *l = list;
- while (l)
+ const char *const duphash = problem_data_get_content_or_NULL(pd, FILENAME_DUPHASH);
+ if (duphash != NULL)
+ problem_data_add_text_noteditable(pd, FILENAME_UUID, duphash);
+ else
{
- const char *key = l->data;
- l = l->next;
- struct problem_item *item = g_hash_table_lookup(pd, key);
- /* do not hash items which are binary (item->flags & CD_FLAG_BIN).
- * Their ->content is full file name, with path. Path is always
- * different and will make hash differ even if files are the same.
+ /* start hash */
+ sha1_ctx_t sha1ctx;
+ sha1_begin(&sha1ctx);
+
+ /*
+ * To avoid spurious hash differences, sort keys so that elements are
+ * always processed in the same order:
*/
- if (item->flags & CD_FLAG_BIN)
- continue;
- sha1_hash(&sha1ctx, item->content, strlen(item->content));
- }
- g_list_free(list);
+ GList *list = g_hash_table_get_keys(pd);
+ list = g_list_sort(list, (GCompareFunc)strcmp);
+ GList *l = list;
+ while (l)
+ {
+ const char *key = l->data;
+ l = l->next;
+ struct problem_item *item = g_hash_table_lookup(pd, key);
+ /* do not hash items which are binary (item->flags & CD_FLAG_BIN).
+ * Their ->content is full file name, with path. Path is always
+ * different and will make hash differ even if files are the same.
+ */
+ if (item->flags & CD_FLAG_BIN)
+ continue;
+ sha1_hash(&sha1ctx, item->content, strlen(item->content));
+ }
+ g_list_free(list);
- /* end hash */
- char hash_bytes[SHA1_RESULT_LEN];
- sha1_end(&sha1ctx, hash_bytes);
- char hash_str[SHA1_RESULT_LEN*2 + 1];
- bin2hex(hash_str, hash_bytes, SHA1_RESULT_LEN)[0] = '\0';
+ /* end hash */
+ char hash_bytes[SHA1_RESULT_LEN];
+ sha1_end(&sha1ctx, hash_bytes);
+ char hash_str[SHA1_RESULT_LEN*2 + 1];
+ bin2hex(hash_str, hash_bytes, SHA1_RESULT_LEN)[0] = '\0';
- problem_data_add_text_noteditable(pd, FILENAME_DUPHASH, hash_str);
+ problem_data_add_text_noteditable(pd, FILENAME_UUID, hash_str);
+ }
}
}
--
1.8.1.2
11 years, 2 months
[PATCH] libreport: make [p]error_msg[_and_die] more fork-in-multithreading-app safe
by Denys Vlasenko
Jakub, can you double-check that I did not add
a bug somewhere there?
I run-tested it, but code review will still be useful.
--
vda
diff -x '*.po' -d -urpN libreport.5/src/lib/logging.c libreport.6/src/lib/logging.c
--- libreport.5/src/lib/logging.c 2013-02-07 18:03:32.912987379 +0100
+++ libreport.6/src/lib/logging.c 2013-02-07 17:48:44.235190248 +0100
@@ -26,40 +26,87 @@ int logmode = LOGMODE_STDIO;
int xfunc_error_retval = EXIT_FAILURE;
int g_verbose;
+/* [p]error_msg[_and_die] must be safe after fork in multi-threaded programs.
+ * Therefore we avoid stdio, fflush(), and use _exit() instead of exit().
+ *
+ */
void xfunc_die(void)
{
- exit(xfunc_error_retval);
+ _exit(xfunc_error_retval);
}
+/* If set to 0, will use malloc for long messages */
+#define USE_ALLOCA 1
+
static void verror_msg_helper(const char *s,
va_list p,
- const char* strerr,
+ const char *strerr,
int flags)
{
- char *msg;
- int prefix_len, strerr_len, msgeol_len, used;
-
if (!logmode)
return;
- used = vasprintf(&msg, s, p);
- if (used < 0)
- return;
-
/* This is ugly and costs +60 bytes compared to multiple
* fprintf's, but is guaranteed to do a single write.
* This is needed for e.g. when multiple children
* can produce log messages simultaneously. */
- prefix_len = msg_prefix[0] ? strlen(msg_prefix) + 2 : 0;
- strerr_len = strerr ? strlen(strerr) : 0;
- msgeol_len = strlen(msg_eol);
+ int prefix_len = msg_prefix[0] ? strlen(msg_prefix) + 2 : 0;
+ int strerr_len = strerr ? strlen(strerr) : 0;
+ int msgeol_len = strlen(msg_eol);
+ int used;
+
+ /* Try to format the message in a fixed buffer.
+ * This eliminates malloc.
+ * Main reason isn't the speed optimization, but to make
+ * short logging safe after fork in multithreaded libraries.
+ */
+ char buf[1024];
+ va_list p2;
+ va_copy(p2, p);
+ if (prefix_len < sizeof(buf))
+ used = vsnprintf(buf + prefix_len, sizeof(buf) - prefix_len, s, p2);
+ else
+ used = vsnprintf(buf, 0, s, p2);
+ va_end(p2);
+
+ char *msg = buf;
+
/* +3 is for ": " before strerr and for terminating NUL */
- msg = (char*) xrealloc(msg, prefix_len + used + strerr_len + msgeol_len + 3);
- /* TODO: maybe use writev instead of memmoving? Need full_writev? */
+ unsigned total_len = prefix_len + used + strerr_len + msgeol_len + 3;
+
+#if USE_ALLOCA
+ if (total_len >= sizeof(buf))
+ {
+ msg = alloca(total_len);
+ used = vsnprintf(msg + prefix_len, total_len - prefix_len, s, p);
+ }
+#else
+#define LOGMODE_DIE ((unsigned)INT_MAX + 1)
+ char *malloced = NULL;
+ if (total_len >= sizeof(buf))
+ {
+ /* Nope, need to malloc the buffer.
+ * Can't use xmalloc: it calls error_msg_and_die on failure,
+ * that will result in a recursion.
+ */
+ msg = malloced = malloc(total_len);
+ if (!msg)
+ {
+ /* Same as xmalloc error */
+ msg = strcpy(buf, "Out of memory, exiting\n");
+ used = strlen(msg) - 1;
+ msgeol_len = 1; /* '\n' */
+ prefix_len = 0;
+ flags |= LOGMODE_DIE;
+ goto send_it;
+ }
+ used = vsnprintf(msg + prefix_len, total_len - prefix_len, s, p);
+ }
+#endif
+
if (prefix_len) {
char *p;
- memmove(msg + prefix_len, msg, used);
used += prefix_len;
p = stpcpy(msg, msg_prefix);
p[0] = ':';
@@ -75,8 +122,11 @@ static void verror_msg_helper(const char
}
strcpy(&msg[used], msg_eol);
+#if !USE_ALLOCA
+ send_it:
+#endif
if (flags & LOGMODE_STDIO) {
- fflush(stdout);
+ /*fflush(stdout); - unsafe after fork! */
full_write(STDERR_FILENO, msg, used + msgeol_len);
}
msg[used] = '\0'; /* remove msg_eol (usually "\n") */
@@ -86,7 +136,13 @@ static void verror_msg_helper(const char
if ((flags & LOGMODE_CUSTOM) && g_custom_logger) {
g_custom_logger(msg + prefix_len);
}
- free(msg);
+
+#if !USE_ALLOCA
+ free(malloced);
+
+ if (flags & LOGMODE_DIE)
+ xfunc_die();
+#endif
}
void log_msg(const char *s, ...)
11 years, 3 months
[LIBREPORT PATCH] report-gtk: gtk_scrolled_window_add_with_viewport has been deprecated
by Jakub Filak
- closing #122
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/gui-wizard-gtk/wizard.c | 8 ++++++++
1 file changed, 8 insertions(+)
diff --git a/src/gui-wizard-gtk/wizard.c b/src/gui-wizard-gtk/wizard.c
index 335e1b4..e18c31c 100644
--- a/src/gui-wizard-gtk/wizard.c
+++ b/src/gui-wizard-gtk/wizard.c
@@ -751,7 +751,15 @@ static void tv_details_row_activated(
gtk_widget_set_size_request(scrolled, 640, 480);
gtk_widget_show(scrolled);
+#if (GTK_MAJOR_VERSION == 3 && GTK_MINOR_VERSION < 8)
+ /* http://developer.gnome.org/gtk3/unstable/GtkScrolledWindow.html#gtk-scrol... */
+ /* gtk_scrolled_window_add_with_viewport has been deprecated since version 3.8 and should not be used in newly-written code. */
gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(scrolled), textview);
+#else
+ /* gtk_container_add() will now automatically add a GtkViewport if the child doesn't implement GtkScrollable. */
+ gtk_container_add(GTK_CONTAINER(scrolled), textview);
+#endif
+
gtk_widget_show(textview);
load_text_to_text_view(GTK_TEXT_VIEW(textview), item_name);
--
1.8.1
11 years, 3 months
[LIBREPORT PATCH] move 'reporter-mailx' from post-create event to notify(-dup) event
by Jakub Filak
- closing #558
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/plugins/mailx_event.conf | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/plugins/mailx_event.conf b/src/plugins/mailx_event.conf
index a8c5d11..65f3c07 100644
--- a/src/plugins/mailx_event.conf
+++ b/src/plugins/mailx_event.conf
@@ -1,3 +1,5 @@
-EVENT=post-create reporter-mailx --notify-only -c /etc/libreport/plugins/mailx.conf
+EVENT=notify reporter-mailx --notify-only -c /etc/libreport/plugins/mailx.conf
+
+EVENT=notify-dup reporter-mailx --notify-only -c /etc/libreport/plugins/mailx.conf
EVENT=report_Mailx reporter-mailx
--
1.8.1
11 years, 3 months
[LIBREPORT PATCH] reporter-bugzilla: use base64 XMLRPC type for encoded data instead of string type
by Jakub Filak
- obsolete: 'bugzilla.addAttachment' accepted base64 data in string variable
and stored them in database decoded
- current: 'Bug.add_attachment' accepts base64 data but it must be stored in
base64 type, otherwise server doesn't decode the data and stores them as they
are
- related to issue #117
Signed-off-by: Jakub Filak <jfilak(a)redhat.com>
---
src/plugins/rhbz.c | 16 +++++++++++-----
1 file changed, 11 insertions(+), 5 deletions(-)
diff --git a/src/plugins/rhbz.c b/src/plugins/rhbz.c
index 3fb24e3..4dfb19e 100644
--- a/src/plugins/rhbz.c
+++ b/src/plugins/rhbz.c
@@ -668,18 +668,25 @@ int rhbz_attach_blob(struct abrt_xmlrpc *ax, const char *bug_id,
{
func_entry();
- char *encoded64 = encode_base64(data, data_len);
char *fn = xasprintf("File: %s", filename);
xmlrpc_value* result;
int nomail_notify = !!IS_NOMAIL_NOTIFY(flags);
- /* http://www.bugzilla.org/docs/4.2/en/html/api/Bugzilla/WebService/Bug.html... */
- result = abrt_xmlrpc_call(ax, "Bug.add_attachment", "({s:(s),s:s,s:s,s:s,s:s,s:i})",
+ /* http://www.bugzilla.org/docs/4.2/en/html/api/Bugzilla/WebService/Bug.html...
+ *
+ * XMLRPC format options:
+ * s -> string, single argument (char* value)
+ * i -> integer, single argument (int value)
+ * 6 -> base64, two arguments (char* plain data which will be encoded in base64,
+ * size_t number of bytes to encode)
+ */
+ result = abrt_xmlrpc_call(ax, "Bug.add_attachment", "({s:(s),s:s,s:s,s:s,s:6,s:i})",
"ids", bug_id,
"summary", fn,
"file_name", filename,
"content_type", (flags & RHBZ_BINARY_ATTACHMENT) ? "application/octet-stream" : "text/plain",
- "data", encoded64,
+ /* base64 type requires two arguments: char* (plain data) and size_t (length)*/
+ "data", data, (size_t)data_len,
/* Undocumented argument but it works with Red Hat Bugzilla version 4.2.4-7
* and version 4.4.rc1.b02
@@ -687,7 +694,6 @@ int rhbz_attach_blob(struct abrt_xmlrpc *ax, const char *bug_id,
"nomail", nomail_notify
);
- free(encoded64);
free(fn);
if (!result)
return -1;
--
1.8.1
11 years, 3 months
[PATCH] abrt-dump-{oops,xorg}: limit amount of created dirs, add cooldown sleep if exceeded
by Denys Vlasenko
diff -x '*.po' -d -urpN abrt.2/src/plugins/abrt-dump-oops.c abrt.3/src/plugins/abrt-dump-oops.c
--- abrt.2/src/plugins/abrt-dump-oops.c 2013-02-04 12:14:37.000000000 +0100
+++ abrt.3/src/plugins/abrt-dump-oops.c 2013-02-05 13:03:31.193062774 +0100
@@ -19,6 +19,11 @@
#include <syslog.h>
#include "libabrt.h"
+/* How many problem dirs to create at most?
+ * Also causes cooldown sleep if exceeded -
+ * useful when called from a log watcher.
+ */
+#define MAX_DUMPED_DD_COUNT 5
static bool world_readable_dump = false;
static const char *debug_dumps_dir = ".";
@@ -106,7 +111,7 @@ static char *list_of_tainted_modules(con
/* returns number of errors */
static unsigned save_oops_to_dump_dir(GList *oops_list, unsigned oops_cnt)
{
- unsigned countdown = 16; /* do not report hundreds of oopses */
+ unsigned countdown = MAX_DUMPED_DD_COUNT + 1; /* do not report hundreds of oopses */
VERB1 log("Saving %u oopses as dump dirs", oops_cnt >= countdown ? countdown-1 : oops_cnt);
@@ -333,8 +338,13 @@ int main(int argc, char **argv)
);
}
}
- //list_free_with_free(oops_list);
+ list_free_with_free(oops_list);
//oops_list = NULL;
+ if (oops_cnt > MAX_DUMPED_DD_COUNT)
+ {
+ sleep(oops_cnt - MAX_DUMPED_DD_COUNT);
+ }
+
return errors;
}
diff -x '*.po' -d -urpN abrt.2/src/plugins/abrt-dump-xorg.c abrt.3/src/plugins/abrt-dump-xorg.c
--- abrt.2/src/plugins/abrt-dump-xorg.c 2013-02-04 12:14:37.000000000 +0100
+++ abrt.3/src/plugins/abrt-dump-xorg.c 2013-02-05 12:59:05.625968434 +0100
@@ -35,6 +35,13 @@ enum {
OPT_m = 1 << 6,
};
+/* How many problem dirs to create at most?
+ * Also causes cooldown sleep if exceeded -
+ * useful when called from a log watcher.
+ */
+#define MAX_DUMPED_DD_COUNT 5
+
+static unsigned g_bt_count = 0;
static unsigned g_opts;
static const char *debug_dumps_dir = ".";
static unsigned dir_seq_no = 0;
@@ -208,7 +215,8 @@ static void process_xorg_bt(void)
if (g_opts & OPT_o)
printf("%s%s%s\n", bt, reason ? reason : "", reason ? "\n" : "");
if (g_opts & (OPT_d|OPT_D))
- save_bt_to_dump_dir(bt, exe, reason ? reason : "Xorg server crashed");
+ if (g_bt_count <= MAX_DUMPED_DD_COUNT)
+ save_bt_to_dump_dir(bt, exe, reason ? reason : "Xorg server crashed");
free(bt);
}
free(reason);
@@ -281,11 +289,18 @@ int main(int argc, char **argv)
if (strcmp(p, "Backtrace:") == 0)
{
free(line);
+ g_bt_count++;
process_xorg_bt();
continue;
}
free(line);
}
+ if (opts & (OPT_d|OPT_D))
+ {
+ if (g_bt_count > MAX_DUMPED_DD_COUNT)
+ sleep(g_bt_count - MAX_DUMPED_DD_COUNT);
+ }
+
return 0;
}
11 years, 3 months