Message ID | 1337007392-30304-3-git-send-email-mdroth@linux.vnet.ibm.com |
---|---|
State | New |
Headers | show |
On 05/14/2012 08:56 AM, Michael Roth wrote: > From: Luiz Capitulino <lcapitulino@redhat.com> > > Last commit dropped qemu-ga's SIGCHLD handler, used to automatically > reap terminated children processes. This introduced a bug to > qmp_guest_shutdown(): it will generate zombies. > > This problem probably doesn't matter in the success case, as the VM > will shutdown anyway, but let's do the right thing and reap the > created process. This ultimately means that guest-shutdown is now a > synchronous command. > > An interesting side effect is that guest-shutdown is now able to > report an error to the client if shutting down fails. > > Signed-off-by: Luiz Capitulino <lcapitulino@redhat.com> > Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com> > --- > qga/commands-posix.c | 21 ++++++++++++++++----- > 1 files changed, 16 insertions(+), 5 deletions(-) Reviewed-by: Eric Blake <eblake@redhat.com>
diff --git a/qga/commands-posix.c b/qga/commands-posix.c index cb97646..9a59276 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -36,8 +36,9 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err) { - int ret; const char *shutdown_flag; + int ret, status; + pid_t rpid, pid; slog("guest-shutdown called, mode: %s", mode); if (!has_mode || strcmp(mode, "powerdown") == 0) { @@ -52,8 +53,8 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err) return; } - ret = fork(); - if (ret == 0) { + pid = fork(); + if (pid == 0) { /* child, start the shutdown */ setsid(); fclose(stdin); @@ -66,9 +67,19 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err) slog("guest-shutdown failed: %s", strerror(errno)); } exit(!!ret); - } else if (ret < 0) { - error_set(err, QERR_UNDEFINED_ERROR); + } else if (pid < 0) { + goto exit_err; } + + do { + rpid = waitpid(pid, &status, 0); + } while (rpid == -1 && errno == EINTR); + if (rpid == pid && WIFEXITED(status) && !WEXITSTATUS(status)) { + return; + } + +exit_err: + error_set(err, QERR_UNDEFINED_ERROR); } typedef struct GuestFileHandle {