tests/qtest: libqtest: Introduce qtest_wait_qemu()

Introduce an API for qtest to wait for the QEMU process to terminate.

Suggested-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Signed-off-by: Bin Meng <bin.meng@windriver.com>
Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20221028045736.679903-7-bin.meng@windriver.com>
Signed-off-by: Thomas Huth <thuth@redhat.com>
This commit is contained in:
Bin Meng 2022-10-28 12:57:31 +08:00 committed by Thomas Huth
parent 1b0f1b14fe
commit 69c056fbc0
2 changed files with 47 additions and 25 deletions

View File

@ -156,37 +156,14 @@ void qtest_set_expected_status(QTestState *s, int status)
s->expected_status = status; s->expected_status = status;
} }
void qtest_kill_qemu(QTestState *s) static void qtest_check_status(QTestState *s)
{ {
pid_t pid = s->qemu_pid;
#ifndef _WIN32
int wstatus;
#else
DWORD ret;
#endif
/* Skip wait if qtest_probe_child already reaped. */
if (pid != -1) {
#ifndef _WIN32
kill(pid, SIGTERM);
TFR(pid = waitpid(s->qemu_pid, &s->wstatus, 0));
assert(pid == s->qemu_pid);
#else
TerminateProcess((HANDLE)pid, s->expected_status);
ret = WaitForSingleObject((HANDLE)pid, INFINITE);
assert(ret == WAIT_OBJECT_0);
GetExitCodeProcess((HANDLE)pid, &s->exit_code);
CloseHandle((HANDLE)pid);
#endif
s->qemu_pid = -1;
}
/* /*
* Check whether qemu exited with expected exit status; anything else is * Check whether qemu exited with expected exit status; anything else is
* fishy and should be logged with as much detail as possible. * fishy and should be logged with as much detail as possible.
*/ */
#ifndef _WIN32 #ifndef _WIN32
wstatus = s->wstatus; int wstatus = s->wstatus;
if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != s->expected_status) { if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) != s->expected_status) {
fprintf(stderr, "%s:%d: kill_qemu() tried to terminate QEMU " fprintf(stderr, "%s:%d: kill_qemu() tried to terminate QEMU "
"process but encountered exit status %d (expected %d)\n", "process but encountered exit status %d (expected %d)\n",
@ -212,6 +189,42 @@ void qtest_kill_qemu(QTestState *s)
#endif #endif
} }
void qtest_wait_qemu(QTestState *s)
{
#ifndef _WIN32
pid_t pid;
TFR(pid = waitpid(s->qemu_pid, &s->wstatus, 0));
assert(pid == s->qemu_pid);
#else
DWORD ret;
ret = WaitForSingleObject((HANDLE)s->qemu_pid, INFINITE);
assert(ret == WAIT_OBJECT_0);
GetExitCodeProcess((HANDLE)s->qemu_pid, &s->exit_code);
CloseHandle((HANDLE)s->qemu_pid);
#endif
qtest_check_status(s);
}
void qtest_kill_qemu(QTestState *s)
{
/* Skip wait if qtest_probe_child() already reaped */
if (s->qemu_pid != -1) {
#ifndef _WIN32
kill(s->qemu_pid, SIGTERM);
#else
TerminateProcess((HANDLE)s->qemu_pid, s->expected_status);
#endif
qtest_wait_qemu(s);
s->qemu_pid = -1;
return;
}
qtest_check_status(s);
}
static void kill_qemu_hook_func(void *s) static void kill_qemu_hook_func(void *s)
{ {
qtest_kill_qemu(s); qtest_kill_qemu(s);

View File

@ -75,6 +75,15 @@ QTestState *qtest_init_without_qmp_handshake(const char *extra_args);
*/ */
QTestState *qtest_init_with_serial(const char *extra_args, int *sock_fd); QTestState *qtest_init_with_serial(const char *extra_args, int *sock_fd);
/**
* qtest_wait_qemu:
* @s: #QTestState instance to operate on.
*
* Wait for the QEMU process to terminate. It is safe to call this function
* multiple times.
*/
void qtest_wait_qemu(QTestState *s);
/** /**
* qtest_kill_qemu: * qtest_kill_qemu:
* @s: #QTestState instance to operate on. * @s: #QTestState instance to operate on.