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