From 4ebcd3879910bcc41c7cee3578337381ab092121 Mon Sep 17 00:00:00 2001 From: Ian Jackson Date: Wed, 4 Jan 2017 00:44:45 +0000 Subject: [PATCH] Use the self-pipe trick to fix the signal handling bug. Closes:#850079. Signed-off-by: Ian Jackson --- debian/changelog | 4 +- events.c | 103 ++++++++++++++++++++++++++++++++++++++++++++++- events.h | 2 + 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 Tue, 03 Jan 2017 23:19:00 +0000 diff --git a/events.c b/events.c index 28e1e29..beeb2e8 100644 --- a/events.c +++ b/events.c @@ -38,6 +38,9 @@ #include #include +#include +#include +#include #include "twm.h" #include #include "add_window.h" @@ -63,6 +66,9 @@ #include /* RAISEDELAY */ #include #endif +#include +#include +#include extern void IconDown(); /* djhjr - 4/26/99 */ @@ -360,6 +366,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: @@ -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 (); } } diff --git a/events.h b/events.h index 8d42304..498ef1e 100644 --- a/events.h +++ b/events.h @@ -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; diff --git a/twm.c b/twm.c index 1402eee..54b8957 100644 --- a/twm.c +++ b/twm.c @@ -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) -- 2.30.2