summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Jackson <ijackson@chiark.greenend.org.uk>2017-01-04 00:44:45 +0000
committerIan Jackson <ijackson@chiark.greenend.org.uk>2017-01-04 01:05:59 +0000
commit4ebcd3879910bcc41c7cee3578337381ab092121 (patch)
tree76f4545408981a69a3064a568c34e5c157e7d720
parente4a2a28e51f9a4f57ef146406579d72be894a520 (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/changelog4
-rw-r--r--events.c103
-rw-r--r--events.h2
-rw-r--r--twm.c8
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
diff --git a/events.c b/events.c
index 28e1e29..beeb2e8 100644
--- a/events.c
+++ b/events.c
@@ -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 ();
}
}
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)