diff options
author | Ian Jackson <ijackson@chiark.greenend.org.uk> | 2017-01-04 00:44:45 +0000 |
---|---|---|
committer | Ian Jackson <ijackson@chiark.greenend.org.uk> | 2017-01-04 01:05:59 +0000 |
commit | 4ebcd3879910bcc41c7cee3578337381ab092121 (patch) | |
tree | 76f4545408981a69a3064a568c34e5c157e7d720 | |
parent | e4a2a28e51f9a4f57ef146406579d72be894a520 (diff) |
Use the self-pipe trick to fix the signal handling bug.
Closes:#850079.
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
-rw-r--r-- | debian/changelog | 4 | ||||
-rw-r--r-- | events.c | 103 | ||||
-rw-r--r-- | events.h | 2 | ||||
-rw-r--r-- | twm.c | 8 |
4 files changed, 111 insertions, 6 deletions
diff --git a/debian/changelog b/debian/changelog index a41b500..f404585 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,6 +1,8 @@ vtwm (5.4.7-5~) unstable; urgency=medium - * + Bugfix: + * Use the self-pipe trick to fix the signal handling bug, instead + of sigprocmask. Closes:#850079. -- Ian Jackson <ijackson@chiark.greenend.org.uk> Tue, 03 Jan 2017 23:19:00 +0000 @@ -38,6 +38,9 @@ #include <stdio.h> #include <string.h> +#include <signal.h> +#include <poll.h> +#include <errno.h> #include "twm.h" #include <X11/Xatom.h> #include "add_window.h" @@ -63,6 +66,9 @@ #include <sys/types.h> /* RAISEDELAY */ #include <unistd.h> #endif +#include <unistd.h> +#include <assert.h> +#include <sys/fcntl.h> extern void IconDown(); /* djhjr - 4/26/99 */ @@ -362,6 +368,68 @@ Bool DispatchEvent () /*********************************************************************** * + * Procedures: + * HandleSignal use instead of signal + * + *********************************************************************** + */ + +#define HANDLE_SIG_MAX 256 /* increase means changing type written to pipe */ + +static SigProc signaltable[HANDLE_SIG_MAX]; +static int sigselfpipe[2] = { -1, -1 }; + +static void +SelfPipeHandler(sig) + int sig; +{ + unsigned char sigchar = sig; + int esave; + + esave = errno; + write(sigselfpipe[1], &sigchar, 1); + errno = esave; +} + +void +HandleSignal(sig, func) + int sig; + SigProc func; +{ + struct sigaction sa; + int r, i; + + if (sigselfpipe[0] == -1) { + r = pipe(sigselfpipe); + if (r) { perror("pipe for signals"); exit(-1); } + for (i = 0; i < 2; i++) { + r = fcntl(sigselfpipe[i], F_GETFL); + if (r<0) { perror("fcntl get for pipe"); exit(-1); } + r |= O_NONBLOCK; + r = fcntl(sigselfpipe[i], F_SETFL, r); + if (r<0) { perror("fcntl get for pipe"); exit(-1); } + } + } + + assert(sig < HANDLE_SIG_MAX); + + r = sigaction(sig, NULL, &sa); + if (r) { perror("sigaction get"); exit(-1); } + + if (sa.sa_handler != SIG_DFL) + return; + + signaltable[sig] = func; + memset(&sa, 0, sizeof(sa)); + sa.sa_handler = SelfPipeHandler; + sigemptyset(&sa.sa_mask); + sa.sa_flags = SA_RESTART; + r = sigaction(sig, &sa, NULL); + if (r) { perror("sigaction set"); exit(-1); } +} + +/*********************************************************************** + * * Procedure: * HandleEvents - handle X events * @@ -371,6 +439,14 @@ Bool DispatchEvent () void HandleEvents() { + struct pollfd pfds[2]; + pfds[0].fd = ConnectionNumber(dpy); + pfds[0].events = POLLIN|POLLPRI; + pfds[1].fd = sigselfpipe[0]; + pfds[1].events = POLLIN|POLLPRI; + sigset_t emptyset; + sigemptyset(&emptyset); + while (TRUE) { if (enter_flag && !QLength(dpy)) { @@ -384,7 +460,32 @@ HandleEvents() InstallWindowColormaps(ColormapNotify, (TwmWindow *) NULL); } WindowMoved = FALSE; - XNextEvent(dpy, &Event); + while (!XCheckMaskEvent(dpy, -1 /* wot no AllEventMask */, &Event)) { + int r; + unsigned char signum; + r = poll(pfds, 2, -1); + if (r<0 && errno!=EINTR) { + perror("vtwm: poll failed"); + exit(-1); + } + for (;;) { + r = read(sigselfpipe[0], &signum, 1); + if (r < 0) { + if (errno == EINTR) continue; + if (errno == EAGAIN) break; + if (errno == EWOULDBLOCK) break; + perror("vtwm: read signal self-pipe"); + exit(-1); + } + if (!r) { + fputs("signal self-pipe read EOF!",stderr); + exit(-1); + } + assert(signum < HANDLE_SIG_MAX); + assert(signaltable[signum]); + signaltable[signum](signum); + } + } (void) DispatchEvent (); } } @@ -77,6 +77,8 @@ extern void InstallWindowColormaps(); extern void RedoDoorName(); /* djhjr - 2/28/99 */ extern void RedoListWindow(); /* djhjr - 3/1/99 */ +extern void HandleSignal(); + extern event_proc EventHandler[]; extern Window DragWindow; extern int origDragX; @@ -258,13 +258,13 @@ main(argc, argv, environ) /* djhjr - 6/22/01 */ #ifndef NO_SOUND_SUPPORT #define sounddonehandler(sig) \ - if (signal (sig, SIG_IGN) != SIG_IGN) (void) signal (sig, PlaySoundDone) + HandleSignal (sig, PlaySoundDone) #else #define sounddonehandler(sig) \ - if (signal (sig, SIG_IGN) != SIG_IGN) (void) signal (sig, Done) + HandleSignal (sig, Done) #endif #define donehandler(sig) \ - if (signal (sig, SIG_IGN) != SIG_IGN) (void) signal (sig, Done) + HandleSignal (sig, Done) sounddonehandler (SIGINT); sounddonehandler (SIGHUP); @@ -282,7 +282,7 @@ main(argc, argv, environ) #undef donehandler /* djhjr - 7/31/98 */ - signal (SIGUSR1, QueueRestartVtwm); + HandleSignal (SIGUSR1, QueueRestartVtwm); Home = getenv("HOME"); if (Home == NULL) |