mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-05 00:33:55 -06:00
qemu-ga: guest-suspend: make the API synchronous
Currently, qemu-ga has a SIGCHLD handler that automatically reaps terminated children processes. The idea is to avoid having qemu-ga commands blocked waiting for children to terminate. That approach has two problems: 1. qemu-ga is unable to detect errors in the child, meaning that qemu-ga returns success even if the child fails to perform its task 2. if a command does depend on the child exit status, the command has to play tricks to bypass the automatic reaper Case 2 impacts the guest-suspend-* API, because it has to execute an external program to check for suspend support. Today, to bypass the automatic reaper, suspend code has to double fork and pass exit status information through a pipe. Besides being complex, this is prone to race condition bugs. Indeed, the current code does have such bugs. Making the guest-suspend-* API synchronous (ie. by dropping the SIGCHLD handler and calling waitpid() from commands) is a much simpler approach, which fixes current race conditions bugs and enables commands to detect errors in the child. This commit does just that. There's a side effect though, guest-shutdown will generate zombies if shutting down fails. This will be fixed by the next commit. Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com> Reviewed-by: Eric Blake <eblake@redhat.com> Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
This commit is contained in:
parent
226a48949c
commit
dc8764f061
2 changed files with 54 additions and 89 deletions
17
qemu-ga.c
17
qemu-ga.c
|
@ -104,16 +104,9 @@ static void quit_handler(int sig)
|
|||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
/* reap _all_ terminated children */
|
||||
static void child_handler(int sig)
|
||||
{
|
||||
int status;
|
||||
while (waitpid(-1, &status, WNOHANG) > 0) /* NOTHING */;
|
||||
}
|
||||
|
||||
static gboolean register_signal_handlers(void)
|
||||
{
|
||||
struct sigaction sigact, sigact_chld;
|
||||
struct sigaction sigact;
|
||||
int ret;
|
||||
|
||||
memset(&sigact, 0, sizeof(struct sigaction));
|
||||
|
@ -130,14 +123,6 @@ static gboolean register_signal_handlers(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
memset(&sigact_chld, 0, sizeof(struct sigaction));
|
||||
sigact_chld.sa_handler = child_handler;
|
||||
sigact_chld.sa_flags = SA_NOCLDSTOP;
|
||||
ret = sigaction(SIGCHLD, &sigact_chld, NULL);
|
||||
if (ret == -1) {
|
||||
g_error("error configuring signal handler: %s", strerror(errno));
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue