From d4a8c718600130d9242b3eda29f1ff71f8f3a912 Mon Sep 17 00:00:00 2001 From: Denys Vlasenko Date: Fri, 15 Apr 2011 16:59:57 +0200 Subject: small improvement for rescanning in abrt-gui When, say, reported_to is changed, inotify doesn't see it two dir levels up. abrt-gui needs a bit of help from wizard by sending SIGCHLD, and treating it as "please rescan" request. Signed-off-by: Denys Vlasenko --- src/gui-gtk/abrt-gtk.c | 2 +- src/gui-gtk/main.c | 74 ++++++++++++++++++++++++++++++++++++++++++-------- 2 files changed, 63 insertions(+), 13 deletions(-) (limited to 'src/gui-gtk') diff --git a/src/gui-gtk/abrt-gtk.c b/src/gui-gtk/abrt-gtk.c index 3b4ca4ee..158cb3ad 100644 --- a/src/gui-gtk/abrt-gtk.c +++ b/src/gui-gtk/abrt-gtk.c @@ -109,7 +109,7 @@ static void on_row_activated_cb(GtkTreeView *treeview, GtkTreePath *path, GtkTre if (pid == 0) { /* Undo signal(SIGCHLD, SIG_IGN), or child inherits it and gets terribly confused */ - signal(SIGCHLD, SIG_DFL); + /*signal(SIGCHLD, SIG_DFL); - not needed, we dont set it to SIG_IGN in main anymore */ const char *dirname= g_value_get_string(&d_dir); VERB1 log("Executing: %s %s", "bug-reporting-wizard", dirname); diff --git a/src/gui-gtk/main.c b/src/gui-gtk/main.c index b3f6bdc2..ec2904b1 100644 --- a/src/gui-gtk/main.c +++ b/src/gui-gtk/main.c @@ -31,6 +31,56 @@ static int inotify_fd = -1; static GIOChannel *channel_inotify; static int channel_inotify_event_id = -1; static char **s_dirs; +static int s_signal_pipe[2]; + + +static void rescan_and_refresh(void) +{ + GtkTreePath *old_path = get_cursor(); + //log("old_path1:'%s'", gtk_tree_path_to_string(old_path)); //leak + + rescan_dirs_and_add_to_dirlist(); + + /* Try to restore cursor position */ + //log("old_path2:'%s'", gtk_tree_path_to_string(old_path)); //leak + sanitize_cursor(old_path); + if (old_path) + gtk_tree_path_free(old_path); +} + + +static void handle_signal(int signo) +{ + int save_errno = errno; + + // Enable for debugging only, malloc/printf are unsafe in signal handlers + //VERB3 log("Got signal %d", signo); + + uint8_t sig_caught = signo; + if (write(s_signal_pipe[1], &sig_caught, 1)) + /* we ignore result, if() shuts up stupid compiler */; + + errno = save_errno; +} + +static gboolean handle_signal_pipe(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused) +{ + /* It can only be SIGCHLD. Therefore we do not check the result, + * and eat more than one byte at once: why refresh twice? + */ + gchar buf[16]; + gsize bytes_read; + g_io_channel_read(gio, buf, sizeof(buf), &bytes_read); + + /* Destroy zombies */ + while (waitpid(-1, NULL, WNOHANG) > 0) + continue; + + rescan_and_refresh(); + + return TRUE; /* "please don't remove this event" */ +} + static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused); @@ -71,22 +121,13 @@ static void close_notify(void) /* Inotify handler */ static gboolean handle_inotify_cb(GIOChannel *gio, GIOCondition condition, gpointer ptr_unused) { - GtkTreePath *old_path = get_cursor(); - //log("old_path1:'%s'", gtk_tree_path_to_string(old_path)); //leak - /* We don't bother reading inotify fd. We simply close and reopen it. * This happens rarely enough to not bother making it efficient. */ close_notify(); init_notify(); - rescan_dirs_and_add_to_dirlist(); - - /* Try to restore cursor position */ - //log("old_path2:'%s'", gtk_tree_path_to_string(old_path)); //leak - sanitize_cursor(old_path); - if (old_path) - gtk_tree_path_free(old_path); + rescan_and_refresh(); return TRUE; /* "please don't remove this event" */ } @@ -209,8 +250,17 @@ int main(int argc, char **argv) sanitize_cursor(NULL); - /* Prevent zombies when we spawn wizard */ - signal(SIGCHLD, SIG_IGN); + /* Set up signal pipe */ + xpipe(s_signal_pipe); + close_on_exec_on(s_signal_pipe[0]); + close_on_exec_on(s_signal_pipe[1]); + ndelay_off(s_signal_pipe[0]); + ndelay_off(s_signal_pipe[1]); + signal(SIGCHLD, handle_signal); + g_io_add_watch(g_io_channel_unix_new(s_signal_pipe[0]), + G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP | G_IO_NVAL, + handle_signal_pipe, + NULL); /* Enter main loop */ gtk_main(); -- cgit