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>
master
Stefan Hajnoczi 2014-02-17 16:33:35 +01:00
parent cef60c925c
commit b15d422a23
1 changed files with 25 additions and 6 deletions

View File

@ -44,6 +44,7 @@ struct QTestState
bool irq_level[MAX_IRQ]; bool irq_level[MAX_IRQ];
GString *rx; GString *rx;
pid_t qemu_pid; /* our child QEMU process */ pid_t qemu_pid; /* our child QEMU process */
struct sigaction sigact_old; /* restored on exit */
}; };
#define g_assert_no_errno(ret) do { \ #define g_assert_no_errno(ret) do { \
@ -88,6 +89,19 @@ static int socket_accept(int sock)
return ret; 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 *qtest_init(const char *extra_args)
{ {
QTestState *s; QTestState *s;
@ -96,6 +110,7 @@ QTestState *qtest_init(const char *extra_args)
gchar *qmp_socket_path; gchar *qmp_socket_path;
gchar *command; gchar *command;
const char *qemu_binary; const char *qemu_binary;
struct sigaction sigact;
qemu_binary = getenv("QTEST_QEMU_BINARY"); qemu_binary = getenv("QTEST_QEMU_BINARY");
g_assert(qemu_binary != NULL); g_assert(qemu_binary != NULL);
@ -108,6 +123,14 @@ QTestState *qtest_init(const char *extra_args)
sock = init_socket(socket_path); sock = init_socket(socket_path);
qmpsock = init_socket(qmp_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(); s->qemu_pid = fork();
if (s->qemu_pid == 0) { if (s->qemu_pid == 0) {
command = g_strdup_printf("exec %s " command = g_strdup_printf("exec %s "
@ -148,13 +171,9 @@ QTestState *qtest_init(const char *extra_args)
void qtest_quit(QTestState *s) void qtest_quit(QTestState *s)
{ {
int status; sigaction(SIGABRT, &s->sigact_old, NULL);
if (s->qemu_pid != -1) {
kill(s->qemu_pid, SIGTERM);
waitpid(s->qemu_pid, &status, 0);
}
kill_qemu(s);
close(s->fd); close(s->fd);
close(s->qmp_fd); close(s->qmp_fd);
g_string_free(s->rx, true); g_string_free(s->rx, true);