From d766825190615bc0b1b57d2837475cdec1a075de Mon Sep 17 00:00:00 2001 From: Stefan Hajnoczi Date: Thu, 27 Mar 2014 15:09:50 +0100 Subject: [PATCH] qtest: Keep list of qtest instances for SIGABRT handler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Keep track of active qtest instances so we can kill them when the test aborts. This ensures no QEMU processes are left running after test failure. Signed-off-by: Stefan Hajnoczi Reviewed-by: Marcel Apfelbaum Signed-off-by: Andreas Färber --- tests/libqtest.c | 47 +++++++++++++++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 10 deletions(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index 2b90e4a76e..d9e3a33817 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -48,6 +48,9 @@ struct QTestState struct sigaction sigact_old; /* restored on exit */ }; +static GList *qtest_instances; +static struct sigaction sigact_old; + #define g_assert_no_errno(ret) do { \ g_assert_cmpint(ret, !=, -1); \ } while (0) @@ -104,7 +107,28 @@ static void kill_qemu(QTestState *s) static void sigabrt_handler(int signo) { - kill_qemu(global_qtest); + GList *elem; + for (elem = qtest_instances; elem; elem = elem->next) { + kill_qemu(elem->data); + } +} + +static void setup_sigabrt_handler(void) +{ + struct sigaction sigact; + + /* 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, &sigact_old); +} + +static void cleanup_sigabrt_handler(void) +{ + sigaction(SIGABRT, &sigact_old, NULL); } QTestState *qtest_init(const char *extra_args) @@ -115,7 +139,6 @@ 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); @@ -128,13 +151,12 @@ 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); + /* Only install SIGABRT handler once */ + if (!qtest_instances) { + setup_sigabrt_handler(); + } + + qtest_instances = g_list_prepend(qtest_instances, s); s->qemu_pid = fork(); if (s->qemu_pid == 0) { @@ -180,7 +202,12 @@ QTestState *qtest_init(const char *extra_args) void qtest_quit(QTestState *s) { - sigaction(SIGABRT, &s->sigact_old, NULL); + /* Uninstall SIGABRT handler on last instance */ + if (qtest_instances && !qtest_instances->next) { + cleanup_sigabrt_handler(); + } + + qtest_instances = g_list_remove(qtest_instances, s); kill_qemu(s); close(s->fd);