summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Jackson <ijackson@chiark.greenend.org.uk>2017-01-03 00:44:35 +0000
committerIan Jackson <ijackson@chiark.greenend.org.uk>2017-01-03 01:02:41 +0000
commit91b2ee084430dbe5d81d32d15e06b53d931514d9 (patch)
tree4c4d8c97359280219b18f58a0d7623f05f0ae970
parent1e7a92dac7fa412cc79eed3aa5db3050ed5b6b4c (diff)
Block signals except during the event loop. Closes:#692233.
Previously we would interrupt whatever we were doing, willy-nilly. Now we wait until the event loop is reentered. Symptoms could include locking up the server with a grab, and/or spinning on the cpu. This patch is not very portable (it uses ppoll) but I think it will work on all Debian architectures. In the longer term we should update to new upstream, where the last commits were in 2013. Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
-rw-r--r--debian/changelog1
-rw-r--r--events.c48
-rw-r--r--events.h4
-rw-r--r--twm.c6
4 files changed, 58 insertions, 1 deletions
diff --git a/debian/changelog b/debian/changelog
index 9acbb8b..b9b206a 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,6 @@
vtwm (5.4.7-4~) unstable; urgency=medium
+ * Block signals during the event loop. Closes:#692233.
* .gitignore: Add a .gitignore covering files outside debian/ generated
by dpkg-buildpackage -uc -b on amd64.
* .gitignore: Add a debian/.gitignore too.
diff --git a/events.c b/events.c
index 28e1e29..7e8c7af 100644
--- a/events.c
+++ b/events.c
@@ -36,8 +36,12 @@
*
***********************************************************************/
+#define _GNU_SOURCE /* for ppoll */
#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"
@@ -362,6 +366,35 @@ Bool DispatchEvent ()
/***********************************************************************
*
+ * Procedures:
+ * BlockSignalsAddToList required for every signal we handle
+ * BlockSignals } signals must be blocked except in
+ * UnBlockSignals } the relevant bit of the event loop
+ *
+ ***********************************************************************
+ */
+
+static _Bool blocksignalslist_initialised;
+static sigset_t blocksignalslist;
+
+void
+BlockSignalsAddToList(sig)
+ int sig;
+{
+ if (!blocksignalslist_initialised++)
+ sigemptyset(&blocksignalslist);
+
+ sigaddset(&blocksignalslist, sig);
+}
+
+void
+BlockSignals()
+{
+ sigprocmask(SIG_BLOCK, &blocksignalslist, NULL);
+}
+
+/***********************************************************************
+ *
* Procedure:
* HandleEvents - handle X events
*
@@ -371,6 +404,12 @@ Bool DispatchEvent ()
void
HandleEvents()
{
+ struct pollfd pfd;
+ pfd.fd = ConnectionNumber(dpy);
+ pfd.events = POLLIN|POLLPRI;
+ sigset_t emptyset;
+ sigemptyset(&emptyset);
+
while (TRUE)
{
if (enter_flag && !QLength(dpy)) {
@@ -384,7 +423,14 @@ HandleEvents()
InstallWindowColormaps(ColormapNotify, (TwmWindow *) NULL);
}
WindowMoved = FALSE;
- XNextEvent(dpy, &Event);
+ while (!XCheckMaskEvent(dpy, -1 /* wot no AllEventMask */, &Event)) {
+ int r;
+ r = ppoll(&pfd, 1, 0, &emptyset);
+ if (r<0 && errno!=EINTR) {
+ perror("vtwm: poll failed");
+ exit(-1);
+ }
+ }
(void) DispatchEvent ();
}
}
diff --git a/events.h b/events.h
index 8d42304..6c447df 100644
--- a/events.h
+++ b/events.h
@@ -77,6 +77,10 @@ extern void InstallWindowColormaps();
extern void RedoDoorName(); /* djhjr - 2/28/99 */
extern void RedoListWindow(); /* djhjr - 3/1/99 */
+extern void BlockSignalsAddToList();
+extern void BlockSignals();
+extern void UnblockSignals();
+
extern event_proc EventHandler[];
extern Window DragWindow;
extern int origDragX;
diff --git a/twm.c b/twm.c
index 1402eee..edb040a 100644
--- a/twm.c
+++ b/twm.c
@@ -258,12 +258,15 @@ main(argc, argv, environ)
/* djhjr - 6/22/01 */
#ifndef NO_SOUND_SUPPORT
#define sounddonehandler(sig) \
+ BlockSignalsAddToList(sig); \
if (signal (sig, SIG_IGN) != SIG_IGN) (void) signal (sig, PlaySoundDone)
#else
#define sounddonehandler(sig) \
+ BlockSignalsAddToList(sig); \
if (signal (sig, SIG_IGN) != SIG_IGN) (void) signal (sig, Done)
#endif
#define donehandler(sig) \
+ BlockSignalsAddToList(sig); \
if (signal (sig, SIG_IGN) != SIG_IGN) (void) signal (sig, Done)
sounddonehandler (SIGINT);
@@ -282,8 +285,11 @@ main(argc, argv, environ)
#undef donehandler
/* djhjr - 7/31/98 */
+ BlockSignalsAddToList(SIGUSR1);
signal (SIGUSR1, QueueRestartVtwm);
+ BlockSignals();
+
Home = getenv("HOME");
if (Home == NULL)
Home = "./";