chiark / gitweb /
Block signals except during the event loop. Closes:#692233.
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 3 Jan 2017 00:44:35 +0000 (00:44 +0000)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Tue, 3 Jan 2017 01:02:41 +0000 (01:02 +0000)
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>
debian/changelog
events.c
events.h
twm.c

index 9acbb8bc4f6ca547c1b06a9d7866156697ebdc5a..b9b206a19c17bbf6ce4c73cced3bfcbc15b92d14 100644 (file)
@@ -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.
index 28e1e29b7f4925e1f1d9f1946f0abfa2163ce980..7e8c7af8eba0f8d4ad2544278073a4d5307d3249 100644 (file)
--- a/events.c
+++ b/events.c
  *
  ***********************************************************************/
 
+#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"
@@ -360,6 +364,35 @@ Bool DispatchEvent ()
 
 \f
 
+/***********************************************************************
+ *
+ *  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:
@@ -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 ();
        }
 }
index 8d4230455681d57de0cdf9cad089aaa1403a5cfb..6c447df1fc20d6e915878139fc383bf384704c8c 100644 (file)
--- 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 1402eee38f3716b2bfc6449a9310f06fa9760657..edb040a322fe10acf9f8f1e4564cda6aed7af903 100644 (file)
--- 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 = "./";