[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH 01/11] Handle terminating signals.



This patch makes qemu handle signals better.  For normal signals
(SIGINT, SIGTERM & friends) it just sets the request_shutdown flag,
making the main_loop exit and qemu taking the usual exit route, with
atexit handlers being called and so on, instead of qemu just being
killed by the signal.

For fatal signals such as SIGSEGV, where the exit handler can't return,
it allows to register clean up handlers which will be called instead of
the atexit handlers.  Those handlers must be save to run in signal context.

Signed-off-by: Gerd Hoffmann <kraxel@xxxxxxxxxx>
---
 Makefile.target |    2 +-
 curses.c        |    2 -
 sdl.c           |    9 +----
 termsig.c       |  104 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 termsig.h       |   15 ++++++++
 vl.c            |    6 +++
 6 files changed, 127 insertions(+), 11 deletions(-)
 create mode 100644 termsig.c
 create mode 100644 termsig.h

diff --git a/Makefile.target b/Makefile.target
index 42162c3..ae05af0 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -472,7 +472,7 @@ endif #CONFIG_DARWIN_USER
 # System emulator target
 ifndef CONFIG_USER_ONLY
 
-OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o net-checksum.o
+OBJS=vl.o osdep.o monitor.o pci.o loader.o isa_mmio.o machine.o net-checksum.o 
termsig.o
 ifdef CONFIG_WIN32
 OBJS+=block-raw-win32.o
 else
diff --git a/curses.c b/curses.c
index 87aa9b3..03580fb 100644
--- a/curses.c
+++ b/curses.c
@@ -346,8 +346,6 @@ void curses_display_init(DisplayState *ds, int full_screen)
     atexit(curses_atexit);
 
 #ifndef _WIN32
-    signal(SIGINT, SIG_DFL);
-    signal(SIGQUIT, SIG_DFL);
 #if defined(SIGWINCH) && defined(KEY_RESIZE)
     /* some curses implementations provide a handler, but we
      * want to be sure this is handled regardless of the library */
diff --git a/sdl.c b/sdl.c
index 0edc4a0..84a9d6d 100644
--- a/sdl.c
+++ b/sdl.c
@@ -476,10 +476,8 @@ static void sdl_refresh(DisplayState *ds)
                 sdl_process_key(&ev->key);
             break;
         case SDL_QUIT:
-            if (!no_quit) {
+            if (!no_quit)
                 qemu_system_shutdown_request();
-                vm_start();    /* In case we're paused */
-            }
             break;
         case SDL_MOUSEMOTION:
             if (gui_grab || kbd_mouse_is_absolute() ||
@@ -636,11 +634,6 @@ void sdl_display_init(DisplayState *ds, int full_screen, 
int no_frame)
         fprintf(stderr, "Could not initialize SDL - exiting\n");
         exit(1);
     }
-#ifndef _WIN32
-    /* NOTE: we still want Ctrl-C to work, so we undo the SDL redirections */
-    signal(SIGINT, SIG_DFL);
-    signal(SIGQUIT, SIG_DFL);
-#endif
 
     ds->dpy_update = sdl_update;
     ds->dpy_resize = sdl_resize;
diff --git a/termsig.c b/termsig.c
new file mode 100644
index 0000000..d0136a8
--- /dev/null
+++ b/termsig.c
@@ -0,0 +1,104 @@
+/*
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; under version 2 of the License.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <signal.h>
+
+#include "qemu-common.h"
+#include "sysemu.h"
+#include "sys-queue.h"
+#include "termsig.h"
+
+#ifdef _WIN32
+
+void termsig_register_handler(void (*func)(void))
+{
+}
+
+void termsig_setup(void)
+{
+}
+
+#else
+
+struct handlers {
+    void (*func)(void);
+    int called;
+    TAILQ_ENTRY(handlers) list;
+};
+static TAILQ_HEAD(dummy, handlers) handlers = TAILQ_HEAD_INITIALIZER(handlers);
+static int termsig;
+
+void fatalsig_register_handler(void (*func)(void))
+{
+    struct handlers *h;
+
+    h = qemu_mallocz(sizeof(*h));
+    if (!h)
+        return;
+    h->func = func;
+    TAILQ_INSERT_TAIL(&handlers, h, list);
+}
+
+static void fatalsig_call_handlers(void)
+{
+    struct handlers *h;
+
+    TAILQ_FOREACH(h, &handlers, list) {
+        if (h->called)
+            continue;
+        h->called++;
+       h->func();
+    }
+}
+
+static void termsig_handler(int signal)
+{
+    switch (signal) {
+    case SIGSEGV:
+    case SIGBUS:
+        fatalsig_call_handlers();
+        abort();
+        break;
+    default:
+        if (termsig) {
+            /* Hmm, we got a exit signal before.  Still running.
+             * Main loop is probably stuck somewhere ... */
+            fatalsig_call_handlers();
+            _exit(1);
+        }
+        qemu_system_shutdown_request();
+        termsig = signal;
+        break;
+    }
+}
+
+void termsig_setup(void)
+{
+    struct sigaction act;
+
+    memset(&act, 0, sizeof(act));
+    act.sa_handler = termsig_handler;
+
+    sigaction(SIGINT,  &act, NULL);
+    sigaction(SIGHUP,  &act, NULL);
+    sigaction(SIGTERM, &act, NULL);
+    sigaction(SIGQUIT, &act, NULL);
+
+    act.sa_flags = SA_RESETHAND | SA_ONSTACK;
+    sigaction(SIGSEGV, &act, NULL);
+    sigaction(SIGBUS,  &act, NULL);
+}
+
+#endif
diff --git a/termsig.h b/termsig.h
new file mode 100644
index 0000000..1cc1cdb
--- /dev/null
+++ b/termsig.h
@@ -0,0 +1,15 @@
+/*
+ * Register cleanup handler.
+ *
+ * These handlers are *only* called for emergeny exits, in case we
+ * can't use the normal exit() and thus atexit() handlers don't work.
+ *
+ * These handlers are called directly from the signal handler and
+ * thus are limited to functions which can safely be called from
+ * signal context (see "man 7 signal").
+ *
+ */
+void fatalsig_register_handler(void (*func)(void));
+
+/* setup signal handlers, called from main() */
+void termsig_setup(void);
diff --git a/vl.c b/vl.c
index e929370..56de905 100644
--- a/vl.c
+++ b/vl.c
@@ -37,6 +37,7 @@
 #include "qemu-char.h"
 #include "block.h"
 #include "audio/audio.h"
+#include "termsig.h"
 
 #include <unistd.h>
 #include <fcntl.h>
@@ -7585,6 +7586,8 @@ static int main_loop(void)
                 timeout = 0;
             }
         } else {
+            if (shutdown_requested)
+                break;
             timeout = 10;
         }
 #ifdef CONFIG_PROFILER
@@ -9031,6 +9034,9 @@ int main(int argc, char **argv)
 #endif
     }
 
+    /* must be after terminal init, SDL changes signal handlers */
+    termsig_setup();
+
     /* Maintain compatibility with multiple stdio monitors */
 
     has_monitor = 0;
-- 
1.5.5.1


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.