qemu-ga: guest-shutdown: use only async-signal-safe functions

POSIX mandates[1] that a child process of a multi-thread program uses
only async-signal-safe functions before exec(). We consider qemu-ga
to be multi-thread, because it uses glib.

However, qmp_guest_shutdown() uses functions that are not
async-signal-safe. Fix it the following way:

- fclose() -> reopen_fd_to_null()
- execl() -> execle()
- exit() -> _exit()
- drop slog() usage (which is not safe)

  [1] http://pubs.opengroup.org/onlinepubs/009695399/functions/fork.html

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:
Luiz Capitulino 2012-05-14 15:25:20 -03:00 committed by Michael Roth
parent d5dd3498eb
commit 3674838cd0
2 changed files with 8 additions and 12 deletions

View File

@ -126,8 +126,7 @@
# @guest-shutdown: # @guest-shutdown:
# #
# Initiate guest-activated shutdown. Note: this is an asynchronous # Initiate guest-activated shutdown. Note: this is an asynchronous
# shutdown request, with no guaruntee of successful shutdown. Errors # shutdown request, with no guarantee of successful shutdown.
# will be logged to guest's syslog.
# #
# @mode: #optional "halt", "powerdown" (default), or "reboot" # @mode: #optional "halt", "powerdown" (default), or "reboot"
# #

View File

@ -37,8 +37,8 @@
void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err) void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
{ {
const char *shutdown_flag; const char *shutdown_flag;
int ret, status;
pid_t rpid, pid; pid_t rpid, pid;
int status;
slog("guest-shutdown called, mode: %s", mode); slog("guest-shutdown called, mode: %s", mode);
if (!has_mode || strcmp(mode, "powerdown") == 0) { if (!has_mode || strcmp(mode, "powerdown") == 0) {
@ -57,16 +57,13 @@ void qmp_guest_shutdown(bool has_mode, const char *mode, Error **err)
if (pid == 0) { if (pid == 0) {
/* child, start the shutdown */ /* child, start the shutdown */
setsid(); setsid();
fclose(stdin); reopen_fd_to_null(0);
fclose(stdout); reopen_fd_to_null(1);
fclose(stderr); reopen_fd_to_null(2);
ret = execl("/sbin/shutdown", "shutdown", shutdown_flag, "+0", execle("/sbin/shutdown", "shutdown", shutdown_flag, "+0",
"hypervisor initiated shutdown", (char*)NULL); "hypervisor initiated shutdown", (char*)NULL, environ);
if (ret) { _exit(EXIT_FAILURE);
slog("guest-shutdown failed: %s", strerror(errno));
}
exit(!!ret);
} else if (pid < 0) { } else if (pid < 0) {
goto exit_err; goto exit_err;
} }