Modified startup notification logic to prevent deadlock in issue 471

git-svn-id: http://tint2.googlecode.com/svn/trunk@735 121b4492-b84c-0410-8b4c-0d4edfb3f3cc
This commit is contained in:
o9000 2015-03-20 22:49:13 +00:00 committed by mrovi9000@gmail.com
parent f6b78ad094
commit a2de8d6e53
2 changed files with 161 additions and 123 deletions

View file

@ -5,7 +5,7 @@ option( ENABLE_BATTERY "Enable battery status plugin" ON )
option( ENABLE_TINT2CONF "Enable tint2conf build, a GTK+2 theme configurator for tint2" ON )
option( ENABLE_EXAMPLES "Install additional tin2rc examples" OFF )
option( ENABLE_RSVG "Rsvg support (launcher only)" ON )
option( ENABLE_SN "Startup notification support" OFF )
option( ENABLE_SN "Startup notification support" ON )
include( FindPkgConfig )
include( CheckLibraryExists )

View file

@ -125,6 +125,9 @@ void init (int argc, char *argv[])
// sigprocmask(SIG_BLOCK, &block_mask, 0);
}
static int sn_pipe_valid = 0;
static int sn_pipe[2];
#ifdef HAVE_SN
static int error_trap_depth = 0;
@ -145,6 +148,14 @@ static void error_trap_pop(SnDisplay *display, Display *xdisplay)
}
static void sigchld_handler(int sig) {
if (!sn_pipe_valid)
return;
ssize_t wur = write(sn_pipe[1], "x", 1);
(void) wur;
fsync(sn_pipe[1]);
}
static void sigchld_handler_async() {
// Wait for all dead processes
pid_t pid;
while ((pid = waitpid(-1, NULL, WNOHANG)) > 0) {
@ -168,7 +179,8 @@ static gint cmp_ptr(gconstpointer a, gconstpointer b) {
else
return 1;
}
#else
static void sigchld_handler_async() {}
#endif // HAVE_SN
void init_X11_pre_config()
@ -204,12 +216,17 @@ void init_X11_post_config()
server.sn_dsp = sn_display_new (server.dsp, error_trap_push, error_trap_pop);
server.pids = g_tree_new (cmp_ptr);
// Setup a handler for child termination
if (pipe(sn_pipe) != 0) {
fprintf(stderr, "Creating pipe failed.\n");
} else {
sn_pipe_valid = 1;
struct sigaction act;
memset (&act, 0, sizeof (struct sigaction));
act.sa_handler = sigchld_handler;
if (sigaction(SIGCHLD, &act, 0)) {
perror("sigaction");
}
}
#endif // HAVE_SN
imlib_context_set_display (server.dsp);
@ -254,6 +271,14 @@ void cleanup()
cleanup_server();
cleanup_timeout();
if (server.dsp) XCloseDisplay(server.dsp);
#ifdef HAVE_SN
if (sn_pipe_valid) {
sn_pipe_valid = 0;
close(sn_pipe[1]);
close(sn_pipe[0]);
}
#endif
}
@ -1106,6 +1131,11 @@ start:
// Create a File Description Set containing x11_fd
FD_ZERO (&fdset);
FD_SET (x11_fd, &fdset);
int maxfd = x11_fd;
if (sn_pipe_valid) {
FD_SET (sn_pipe[0], &fdset);
maxfd = maxfd < sn_pipe[0] ? sn_pipe[0] : maxfd;
}
update_next_timeout();
if (next_timeout.tv_sec >= 0 && next_timeout.tv_usec >= 0)
timeout = &next_timeout;
@ -1113,7 +1143,14 @@ start:
timeout = 0;
// Wait for X Event or a Timer
if (select(x11_fd+1, &fdset, 0, 0, timeout) > 0) {
if (select(maxfd+1, &fdset, 0, 0, timeout) > 0) {
if (FD_ISSET(sn_pipe[0], &fdset)) {
char buffer[1];
ssize_t wur = read(sn_pipe[0], buffer, 1);
(void) wur;
sigchld_handler_async();
}
if (FD_ISSET(x11_fd, &fdset)) {
while (XPending (server.dsp)) {
XNextEvent(server.dsp, &e);
#if HAVE_SN
@ -1352,6 +1389,7 @@ start:
}
}
}
}
callback_timeout_expired();