So, XCloseDisplay doesn't return because the thread that is handling the signal is blocked by the thread holding all of the X GUI elements (Xlib is not natively reentrant). So, the proper solution is to just set a flag in the signal handler, instead, so that the main event loop knows to end the program. The nanosleep was introduced so that we don't block for a long time on XNextEvent.
Patch attached. Thanks, Kevin On Wed, Apr 6, 2011 at 23:57, Kevin Kreamer <ke...@kreamer.org> wrote: > I ran into this, as well. > > Tracing through the code in gdb, it appears that the call to XCloseDisplay > on line 125 of wmdrawer.c does not return, causing a SIGTERM not to > terminate the process. The second SIGTERM sent then tries to free memory > previously freed as part of the code handling the first SIGTERM, causing the > segfault. Commenting out the call to XCloseDisplay "works" in that it > allows a CTRL-C to successfully terminate the process, but I don't think > that's actually the proper solution. > > The real question is, why doesn't XCloseDisplay return? > > Kevin >
--- ../orig/wmdrawer-0.10.5/wmdrawer.c 2004-06-26 14:16:04.000000000 -0400 +++ wmdrawer.c 2011-04-12 23:10:17.000000000 -0400 @@ -44,7 +44,8 @@ #include "pixmaps/defaultHighlightImg.xpm" static void signalHandler (int signum); -static void quit (int status); +static void setExit (int status); +static void quit (void); static void xfreeAllMemory (void); static void buildDock (int argc, char *argv[]); static void setDockIcon (void); @@ -80,6 +81,9 @@ static unsigned int btnDim = 0; static int highlightCol, highlightRow; +static int shouldExit; +static int exitCode; + extern drawerConfig config; extern unsigned int nbRows, nbCols, drawerOK; extern unsigned int useDefaultIconsBg, useDefaultDockIcon, useDefaultHighlightImg; @@ -93,6 +97,8 @@ setDockIcon (); buildDrawer (); buildTooltip (); + exitCode = EXIT_SUCCESS; + shouldExit = 0; action.sa_handler = signalHandler; sigemptyset (&action.sa_mask); action.sa_flags = SA_NOCLDSTOP | SA_NODEFER; @@ -101,29 +107,34 @@ sigaction (SIGCHLD, &action, NULL); eventLoop (); - return 0; + quit (); + return exitCode; } static void signalHandler (int signum) { switch (signum) { case SIGINT: case SIGTERM: - quit (EXIT_SUCCESS); + setExit(EXIT_SUCCESS); break; case SIGCHLD: while (waitpid (-1, NULL, WNOHANG | WUNTRACED) > 0); break; default: - quit (EXIT_FAILURE); + setExit(EXIT_FAILURE); } } -static void quit (int status) { +static void setExit (int status) { + exitCode = status; + shouldExit = 1; +} + +static void quit () { printf ("Bye bye, thx to use %s\n", PACKAGE); xfreeAllMemory (); freeAllMemory (); XCloseDisplay (display); - exit (status); } void xfreeAllMemory (void) { @@ -853,8 +864,17 @@ /* X btn's coord */ int xbtn = 0, ybtn = 0; unsigned int delta, btnIsPressed = 0; + struct timespec tv; + + tv.tv_sec = 0; + tv.tv_nsec = 100000; + + while (shouldExit == 0) { + if (XPending (display) == 0) { + nanosleep(&tv, NULL); + continue; + } - while (True) { XNextEvent (display, &e); rebuildApp (); /* look at X.h & Xlib.h in /usr/X11R6/include/X11/ */ @@ -1012,7 +1032,7 @@ } break; case DestroyNotify: - quit (EXIT_SUCCESS); + setExit(EXIT_SUCCESS); } } }