X-Git-Url: https://repo.jachan.dev/qemu.git/blobdiff_plain/0459650d94d18218808fcabc8c3227d2ee99af39..112e4518f0d38fc3c52e55c7d7e77b66a295ec2b:/os-posix.c diff --git a/os-posix.c b/os-posix.c index 6187301481..e4da406f38 100644 --- a/os-posix.c +++ b/os-posix.c @@ -39,19 +39,16 @@ #include "sysemu/sysemu.h" #include "net/slirp.h" #include "qemu-options.h" +#include "qemu/rcu.h" #ifdef CONFIG_LINUX #include #endif -#ifdef __FreeBSD__ -#include -#endif - static struct passwd *user_pwd; static const char *chroot_dir; static int daemonize; -static int fds[2]; +static int daemon_pipe; void os_setup_early_signal_handling(void) { @@ -208,49 +205,50 @@ static void change_root(void) void os_daemonize(void) { if (daemonize) { - pid_t pid; - - if (pipe(fds) == -1) - exit(1); - - pid = fork(); - if (pid > 0) { - uint8_t status; - ssize_t len; - - close(fds[1]); - - again: - len = read(fds[0], &status, 1); - if (len == -1 && (errno == EINTR)) - goto again; - - if (len != 1) - exit(1); - else if (status == 1) { - fprintf(stderr, "Could not acquire pidfile: %s\n", strerror(errno)); - exit(1); - } else - exit(0); - } else if (pid < 0) + pid_t pid; + int fds[2]; + + if (pipe(fds) == -1) { exit(1); + } + + pid = fork(); + if (pid > 0) { + uint8_t status; + ssize_t len; + + close(fds[1]); - close(fds[0]); - qemu_set_cloexec(fds[1]); + do { + len = read(fds[0], &status, 1); + } while (len < 0 && errno == EINTR); - setsid(); + /* only exit successfully if our child actually wrote + * a one-byte zero to our pipe, upon successful init */ + exit(len == 1 && status == 0 ? 0 : 1); - pid = fork(); - if (pid > 0) - exit(0); - else if (pid < 0) - exit(1); + } else if (pid < 0) { + exit(1); + } + + close(fds[0]); + daemon_pipe = fds[1]; + qemu_set_cloexec(daemon_pipe); - umask(027); + setsid(); + + pid = fork(); + if (pid > 0) { + exit(0); + } else if (pid < 0) { + exit(1); + } + umask(027); signal(SIGTSTP, SIG_IGN); signal(SIGTTOU, SIG_IGN); signal(SIGTTIN, SIG_IGN); + rcu_after_fork(); } } @@ -259,47 +257,36 @@ void os_setup_post(void) int fd = 0; if (daemonize) { - uint8_t status = 0; - ssize_t len; - - again1: - len = write(fds[1], &status, 1); - if (len == -1 && (errno == EINTR)) - goto again1; - - if (len != 1) - exit(1); - if (chdir("/")) { perror("not able to chdir to /"); exit(1); } - TFR(fd = qemu_open("/dev/null", O_RDWR)); - if (fd == -1) - exit(1); + TFR(fd = qemu_open("/dev/null", O_RDWR)); + if (fd == -1) { + exit(1); + } } change_root(); change_process_uid(); if (daemonize) { + uint8_t status = 0; + ssize_t len; + dup2(fd, 0); dup2(fd, 1); dup2(fd, 2); close(fd); - } -} -void os_pidfile_error(void) -{ - if (daemonize) { - uint8_t status = 1; - if (write(fds[1], &status, 1) != 1) { - perror("daemonize. Writing to pipe\n"); + do { + len = write(daemon_pipe, &status, 1); + } while (len < 0 && errno == EINTR); + if (len != 1) { + exit(1); } - } else - fprintf(stderr, "Could not acquire pid file: %s\n", strerror(errno)); + } } void os_set_line_buffering(void)