mirror of https://github.com/xqemu/xqemu.git
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:
parent
d5dd3498eb
commit
3674838cd0
|
@ -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"
|
||||||
#
|
#
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue