* concurrent run of post-create event may mark all processed problems as duplicates of each other and delete all of them * abrtd accepts notifications and pushes a problem directory to a queue * after processing of one problem abrtd pops a directory from the queue and continues of processing with next directory
Signed-off-by: Jakub Filak jfilak@redhat.com --- src/daemon/abrtd.c | 66 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 12 deletions(-)
diff --git a/src/daemon/abrtd.c b/src/daemon/abrtd.c index 1112591..c664a66 100644 --- a/src/daemon/abrtd.c +++ b/src/daemon/abrtd.c @@ -74,6 +74,24 @@ static int child_count = 0; */ static GList *s_pid_list;
+/* + * The post-create event cannot be run concurrently for more problem + * directories. The problem is in searching for duplicates process in case when + * two concurrently processed directories are duplicates of each other. Both of + * the directories are marked as duplicates of each other and are deleted. + * + * This queue is used for serialization of processing of created problem + * directories. + * + * The GIO notify handler pushes new directories to this queue and if the queue was + * empty before push then starts processing of the pushed directory. + * + * Directory processing code pops the processed directory from the queue at the + * end of processing. If the queue is not empty starts processing of the next + * directory which is on the top of the queue. + */ +static GList *s_dir_queue; + enum { EVTYPE_POST_CREATE, EVTYPE_NOTIFY, @@ -291,6 +309,25 @@ static gboolean handle_signal_cb(GIOChannel *gio, GIOCondition condition, gpoint return TRUE; /* "please don't remove this event" */ }
+static gboolean handle_event_output_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr); + +/* Runs post-create event asynchronously. Uses GIOChanel for communication with event process. */ +static void run_post_create_on_dir_async(const char *name) +{ + struct event_processing_state *state = new_event_processing_state(); + state->event_type = EVTYPE_POST_CREATE; + state->dirname = concat_path_file(g_settings_dump_location, name); + + state->child_pid = spawn_event_handler_child(state->dirname, "post-create", &state->child_stdout_fd); + s_pid_list = g_list_prepend(s_pid_list, state); + ndelay_on(state->child_stdout_fd); + + GIOChannel *channel_event_output = my_io_channel_unix_new(state->child_stdout_fd); + /*uint channel_id_event_output =*/ g_io_add_watch(channel_event_output, + G_IO_IN | G_IO_PRI | G_IO_HUP, + handle_event_output_cb, + state); +}
/* Event-processing child output handler (such as "post-create" event) */ static gboolean handle_event_output_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr) @@ -435,11 +472,21 @@ static gboolean handle_event_output_cb(GIOChannel *gio, GIOCondition condition,
/* We stop using this channel */ g_io_channel_unref(gio); + + /* pop the currently processed directory from the incoming queue */ + char *name = s_dir_queue->data; + s_dir_queue = g_list_remove(s_dir_queue, name); + free(name); + + /* if the queue is not empty process directory from */ + /* the top of the incoming queue */ + if (s_dir_queue) + run_post_create_on_dir_async(s_dir_queue->data); + return FALSE; /* "glib, please remove this events source!" */ /* Removing will also drop the last ref to this gio, closing/freeing it */ }
- /* Inotify handler */
static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused) @@ -550,19 +597,14 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin } }
- struct event_processing_state *state = new_event_processing_state(); - state->event_type = EVTYPE_POST_CREATE; - state->dirname = concat_path_file(g_settings_dump_location, name); + const bool empty_queue = s_dir_queue == NULL; + /* push the new directory to the end of the incoming queue */ + s_dir_queue = g_list_append(s_dir_queue, xstrdup(name));
- state->child_pid = spawn_event_handler_child(state->dirname, "post-create", &state->child_stdout_fd); - s_pid_list = g_list_prepend(s_pid_list, state); - ndelay_on(state->child_stdout_fd); + /* if the queue was empty process the current directory */ + if (empty_queue) + run_post_create_on_dir_async(name);
- GIOChannel *channel_event_output = my_io_channel_unix_new(state->child_stdout_fd); - /*uint channel_id_event_output =*/ g_io_add_watch(channel_event_output, - G_IO_IN | G_IO_PRI | G_IO_HUP, - handle_event_output_cb, - state); } /* while */
free(buf);
On 07/30/2012 09:43 AM, Jakub Filak wrote:
- concurrent run of post-create event may mark all processed problems as duplicates of each other and delete all of them
- abrtd accepts notifications and pushes a problem directory to a queue
- after processing of one problem abrtd pops a directory from the queue and continues of processing with next directory
Signed-off-by: Jakub Filak jfilak@redhat.com
src/daemon/abrtd.c | 66 ++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 54 insertions(+), 12 deletions(-)
diff --git a/src/daemon/abrtd.c b/src/daemon/abrtd.c index 1112591..c664a66 100644 --- a/src/daemon/abrtd.c +++ b/src/daemon/abrtd.c @@ -74,6 +74,24 @@ static int child_count = 0; */ static GList *s_pid_list;
+/*
- The post-create event cannot be run concurrently for more problem
- directories. The problem is in searching for duplicates process in case when
- two concurrently processed directories are duplicates of each other. Both of
- the directories are marked as duplicates of each other and are deleted.
- This queue is used for serialization of processing of created problem
- directories.
- The GIO notify handler pushes new directories to this queue and if the queue was
- empty before push then starts processing of the pushed directory.
- Directory processing code pops the processed directory from the queue at the
- end of processing. If the queue is not empty starts processing of the next
- directory which is on the top of the queue.
- */
+static GList *s_dir_queue;
enum { EVTYPE_POST_CREATE, EVTYPE_NOTIFY, @@ -291,6 +309,25 @@ static gboolean handle_signal_cb(GIOChannel *gio, GIOCondition condition, gpoint return TRUE; /* "please don't remove this event" */ }
+static gboolean handle_event_output_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr);
+/* Runs post-create event asynchronously. Uses GIOChanel for communication with event process. */ +static void run_post_create_on_dir_async(const char *name) +{
- struct event_processing_state *state = new_event_processing_state();
- state->event_type = EVTYPE_POST_CREATE;
- state->dirname = concat_path_file(g_settings_dump_location, name);
- state->child_pid = spawn_event_handler_child(state->dirname, "post-create", &state->child_stdout_fd);
- s_pid_list = g_list_prepend(s_pid_list, state);
- ndelay_on(state->child_stdout_fd);
- GIOChannel *channel_event_output = my_io_channel_unix_new(state->child_stdout_fd);
- /*uint channel_id_event_output =*/ g_io_add_watch(channel_event_output,
G_IO_IN | G_IO_PRI | G_IO_HUP,
handle_event_output_cb,
state);
+}
/* Event-processing child output handler (such as "post-create" event) */ static gboolean handle_event_output_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr) @@ -435,11 +472,21 @@ static gboolean handle_event_output_cb(GIOChannel *gio, GIOCondition condition,
/* We stop using this channel */ g_io_channel_unref(gio);
- /* pop the currently processed directory from the incoming queue */
- char *name = s_dir_queue->data;
- s_dir_queue = g_list_remove(s_dir_queue, name);
- free(name);
- /* if the queue is not empty process directory from */
- /* the top of the incoming queue */
- if (s_dir_queue)
run_post_create_on_dir_async(s_dir_queue->data);
- return FALSE; /* "glib, please remove this events source!" */ /* Removing will also drop the last ref to this gio, closing/freeing it */
}
/* Inotify handler */
static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused) @@ -550,19 +597,14 @@ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpoin } }
struct event_processing_state *state = new_event_processing_state();
state->event_type = EVTYPE_POST_CREATE;
state->dirname = concat_path_file(g_settings_dump_location, name);
const bool empty_queue = s_dir_queue == NULL;
/* push the new directory to the end of the incoming queue */
s_dir_queue = g_list_append(s_dir_queue, xstrdup(name));
state->child_pid = spawn_event_handler_child(state->dirname, "post-create", &state->child_stdout_fd);
s_pid_list = g_list_prepend(s_pid_list, state);
ndelay_on(state->child_stdout_fd);
/* if the queue was empty process the current directory */
if (empty_queue)
run_post_create_on_dir_async(name);
GIOChannel *channel_event_output = my_io_channel_unix_new(state->child_stdout_fd);
/*uint channel_id_event_output =*/ g_io_add_watch(channel_event_output,
G_IO_IN | G_IO_PRI | G_IO_HUP,
handle_event_output_cb,
state);
} /* while */
free(buf);
Looks good to me.
crash-catcher@lists.fedorahosted.org