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>
This commit is contained in:
parent
cef60c925c
commit
b15d422a23
@ -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);
|
||||||
|
Loading…
Reference in New Issue
Block a user