Commit d7668251 authored by Stefan Hajnoczi's avatar Stefan Hajnoczi Committed by Andreas Färber
Browse files

qtest: Keep list of qtest instances for SIGABRT handler



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: default avatarStefan Hajnoczi <stefanha@redhat.com>
Reviewed-by: default avatarMarcel Apfelbaum <marcel.a@redhat.com>
Signed-off-by: default avatarAndreas Färber <afaerber@suse.de>
parent 96b8ca47
Loading
Loading
Loading
Loading
+37 −10
Original line number Diff line number Diff line
@@ -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);