qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@redhat.com>
To: qemu-devel@nongnu.org, xen-devel@lists.xensource.com
Cc: Gerd Hoffmann <kraxel@redhat.com>
Subject: [Qemu-devel] [PATCH 01/11] Handle terminating signals.
Date: Mon, 11 Aug 2008 14:32:40 +0200	[thread overview]
Message-ID: <1218457970-11707-2-git-send-email-kraxel@redhat.com> (raw)
In-Reply-To: <1218457970-11707-1-git-send-email-kraxel@redhat.com>

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@redhat.com>
---
 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

  reply	other threads:[~2008-08-11 12:32 UTC|newest]

Thread overview: 18+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2008-08-11 12:32 [Qemu-devel] [PATCH 00/11] merge some xen bits into qemu Gerd Hoffmann
2008-08-11 12:32 ` Gerd Hoffmann [this message]
2008-08-11 19:27   ` [Qemu-devel] [PATCH 01/11] Handle terminating signals Anthony Liguori
2008-08-11 19:52     ` Gerd Hoffmann
2008-08-11 19:30   ` Anthony Liguori
2008-08-11 19:58     ` Gerd Hoffmann
2008-08-12  1:53       ` Anthony Liguori
2008-08-11 12:32 ` [Qemu-devel] [PATCH 02/11] add DisplayState->idle Gerd Hoffmann
2008-08-11 12:36   ` [Qemu-devel] " Samuel Thibault
2008-08-11 12:32 ` [Qemu-devel] [PATCH 03/11] add container_of() macro to osdep.h Gerd Hoffmann
2008-08-11 12:32 ` [Qemu-devel] [PATCH 04/11] move GUI_REFRESH_INTERVAL define from vl.c to console.h Gerd Hoffmann
2008-08-11 12:32 ` [Qemu-devel] [PATCH 05/11] xen: groundwork for xen support Gerd Hoffmann
2008-08-11 12:32 ` [Qemu-devel] [PATCH 06/11] xen: backend driver core Gerd Hoffmann
2008-08-11 12:32 ` [Qemu-devel] [PATCH 07/11] xen: add console backend driver Gerd Hoffmann
2008-08-11 12:32 ` [Qemu-devel] [PATCH 08/11] xen: add framebuffer " Gerd Hoffmann
2008-08-11 12:32 ` [Qemu-devel] [PATCH 09/11] xen: add block device " Gerd Hoffmann
2008-08-11 12:32 ` [Qemu-devel] [PATCH 10/11] xen: add net " Gerd Hoffmann
2008-08-11 12:32 ` [Qemu-devel] [PATCH 11/11] xen: blk & nic configuration via cmd line Gerd Hoffmann

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1218457970-11707-2-git-send-email-kraxel@redhat.com \
    --to=kraxel@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).