summary refs log tree commit diff stats
path: root/tests/libqtest.c
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2014-02-17 16:33:35 +0100
committerStefan Hajnoczi <stefanha@redhat.com>2014-02-19 15:45:51 +0100
commitb15d422a23a3e4cf1b4195af209211eccdb88d51 (patch)
treecc7076f950a07749ba9aef323b2e6b514ca5d9f6 /tests/libqtest.c
parentcef60c925c41563721dc73b1ace7b2f399f72a5b (diff)
downloadfocaccia-qemu-b15d422a23a3e4cf1b4195af209211eccdb88d51.tar.gz
focaccia-qemu-b15d422a23a3e4cf1b4195af209211eccdb88d51.zip
qtest: kill QEMU process on g_assert() failure
The QEMU process stays running if the test case fails.  This patch fixes
the leak by installing a SIGABRT signal handler which invokes
qtest_end().

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'tests/libqtest.c')
-rw-r--r--tests/libqtest.c31
1 files changed, 25 insertions, 6 deletions
diff --git a/tests/libqtest.c b/tests/libqtest.c
index 8b2b2d7fa4..f587d36176 100644
--- a/tests/libqtest.c
+++ b/tests/libqtest.c
@@ -44,6 +44,7 @@ struct QTestState
     bool irq_level[MAX_IRQ];
     GString *rx;
     pid_t qemu_pid;  /* our child QEMU process */
+    struct sigaction sigact_old; /* restored on exit */
 };
 
 #define g_assert_no_errno(ret) do { \
@@ -88,6 +89,19 @@ static int socket_accept(int sock)
     return ret;
 }
 
+static void kill_qemu(QTestState *s)
+{
+    if (s->qemu_pid != -1) {
+        kill(s->qemu_pid, SIGTERM);
+        waitpid(s->qemu_pid, NULL, 0);
+    }
+}
+
+static void sigabrt_handler(int signo)
+{
+    kill_qemu(global_qtest);
+}
+
 QTestState *qtest_init(const char *extra_args)
 {
     QTestState *s;
@@ -96,6 +110,7 @@ QTestState *qtest_init(const char *extra_args)
     gchar *qmp_socket_path;
     gchar *command;
     const char *qemu_binary;
+    struct sigaction sigact;
 
     qemu_binary = getenv("QTEST_QEMU_BINARY");
     g_assert(qemu_binary != NULL);
@@ -108,6 +123,14 @@ QTestState *qtest_init(const char *extra_args)
     sock = init_socket(socket_path);
     qmpsock = init_socket(qmp_socket_path);
 
+    /* Catch SIGABRT to clean up on g_assert() failure */
+    sigact = (struct sigaction){
+        .sa_handler = sigabrt_handler,
+        .sa_flags = SA_RESETHAND,
+    };
+    sigemptyset(&sigact.sa_mask);
+    sigaction(SIGABRT, &sigact, &s->sigact_old);
+
     s->qemu_pid = fork();
     if (s->qemu_pid == 0) {
         command = g_strdup_printf("exec %s "
@@ -148,13 +171,9 @@ QTestState *qtest_init(const char *extra_args)
 
 void qtest_quit(QTestState *s)
 {
-    int status;
-
-    if (s->qemu_pid != -1) {
-        kill(s->qemu_pid, SIGTERM);
-        waitpid(s->qemu_pid, &status, 0);
-    }
+    sigaction(SIGABRT, &s->sigact_old, NULL);
 
+    kill_qemu(s);
     close(s->fd);
     close(s->qmp_fd);
     g_string_free(s->rx, true);