Commit 71e3ceb800ec212acd78f613245bbb82278348d0
1 parent
73fc9742
Daemonize option, by Anthony Liguori.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2261 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
88 additions
and
0 deletions
qemu-doc.texi
| ... | ... | @@ -309,6 +309,12 @@ Start in full screen. |
| 309 | 309 | Store the QEMU process PID in @var{file}. It is useful if you launch QEMU |
| 310 | 310 | from a script. |
| 311 | 311 | |
| 312 | +@item -daemonize | |
| 313 | +Daemonize the QEMU process after initialization. QEMU will not detach from | |
| 314 | +standard IO until it is ready to receive connections on any of its devices. | |
| 315 | +This option is a useful way for external programs to launch QEMU without having | |
| 316 | +to cope with initialization race conditions. | |
| 317 | + | |
| 312 | 318 | @item -win2k-hack |
| 313 | 319 | Use it when installing Windows 2000 to avoid a disk full bug. After |
| 314 | 320 | Windows 2000 is installed, you no longer need this option (this option | ... | ... |
vl.c
| ... | ... | @@ -163,6 +163,7 @@ const char *vnc_display; |
| 163 | 163 | int acpi_enabled = 1; |
| 164 | 164 | int fd_bootchk = 1; |
| 165 | 165 | int no_reboot = 0; |
| 166 | +int daemonize = 0; | |
| 166 | 167 | |
| 167 | 168 | /***********************************************************/ |
| 168 | 169 | /* x86 ISA bus support */ |
| ... | ... | @@ -6018,6 +6019,9 @@ void help(void) |
| 6018 | 6019 | "-no-reboot exit instead of rebooting\n" |
| 6019 | 6020 | "-loadvm file start right away with a saved state (loadvm in monitor)\n" |
| 6020 | 6021 | "-vnc display start a VNC server on display\n" |
| 6022 | +#ifndef _WIN32 | |
| 6023 | + "-daemonize daemonize QEMU after initializing\n" | |
| 6024 | +#endif | |
| 6021 | 6025 | "\n" |
| 6022 | 6026 | "During emulation, the following keys are useful:\n" |
| 6023 | 6027 | "ctrl-alt-f toggle full screen\n" |
| ... | ... | @@ -6098,6 +6102,7 @@ enum { |
| 6098 | 6102 | QEMU_OPTION_vnc, |
| 6099 | 6103 | QEMU_OPTION_no_acpi, |
| 6100 | 6104 | QEMU_OPTION_no_reboot, |
| 6105 | + QEMU_OPTION_daemonize, | |
| 6101 | 6106 | }; |
| 6102 | 6107 | |
| 6103 | 6108 | typedef struct QEMUOption { |
| ... | ... | @@ -6178,6 +6183,7 @@ const QEMUOption qemu_options[] = { |
| 6178 | 6183 | { "cirrusvga", 0, QEMU_OPTION_cirrusvga }, |
| 6179 | 6184 | { "no-acpi", 0, QEMU_OPTION_no_acpi }, |
| 6180 | 6185 | { "no-reboot", 0, QEMU_OPTION_no_reboot }, |
| 6186 | + { "daemonize", 0, QEMU_OPTION_daemonize }, | |
| 6181 | 6187 | { NULL }, |
| 6182 | 6188 | }; |
| 6183 | 6189 | |
| ... | ... | @@ -6408,6 +6414,7 @@ int main(int argc, char **argv) |
| 6408 | 6414 | QEMUMachine *machine; |
| 6409 | 6415 | char usb_devices[MAX_USB_CMDLINE][128]; |
| 6410 | 6416 | int usb_devices_index; |
| 6417 | + int fds[2]; | |
| 6411 | 6418 | |
| 6412 | 6419 | LIST_INIT (&vm_change_state_head); |
| 6413 | 6420 | #ifndef _WIN32 |
| ... | ... | @@ -6826,10 +6833,61 @@ int main(int argc, char **argv) |
| 6826 | 6833 | case QEMU_OPTION_no_reboot: |
| 6827 | 6834 | no_reboot = 1; |
| 6828 | 6835 | break; |
| 6836 | + case QEMU_OPTION_daemonize: | |
| 6837 | + daemonize = 1; | |
| 6838 | + break; | |
| 6829 | 6839 | } |
| 6830 | 6840 | } |
| 6831 | 6841 | } |
| 6832 | 6842 | |
| 6843 | +#ifndef _WIN32 | |
| 6844 | + if (daemonize && !nographic && vnc_display == NULL) { | |
| 6845 | + fprintf(stderr, "Can only daemonize if using -nographic or -vnc\n"); | |
| 6846 | + daemonize = 0; | |
| 6847 | + } | |
| 6848 | + | |
| 6849 | + if (daemonize) { | |
| 6850 | + pid_t pid; | |
| 6851 | + | |
| 6852 | + if (pipe(fds) == -1) | |
| 6853 | + exit(1); | |
| 6854 | + | |
| 6855 | + pid = fork(); | |
| 6856 | + if (pid > 0) { | |
| 6857 | + uint8_t status; | |
| 6858 | + ssize_t len; | |
| 6859 | + | |
| 6860 | + close(fds[1]); | |
| 6861 | + | |
| 6862 | + again: | |
| 6863 | + len = read(fds[0], &status, 1); | |
| 6864 | + if (len == -1 && (errno == EINTR)) | |
| 6865 | + goto again; | |
| 6866 | + | |
| 6867 | + if (len != 1 || status != 0) | |
| 6868 | + exit(1); | |
| 6869 | + else | |
| 6870 | + exit(0); | |
| 6871 | + } else if (pid < 0) | |
| 6872 | + exit(1); | |
| 6873 | + | |
| 6874 | + setsid(); | |
| 6875 | + | |
| 6876 | + pid = fork(); | |
| 6877 | + if (pid > 0) | |
| 6878 | + exit(0); | |
| 6879 | + else if (pid < 0) | |
| 6880 | + exit(1); | |
| 6881 | + | |
| 6882 | + umask(027); | |
| 6883 | + chdir("/"); | |
| 6884 | + | |
| 6885 | + signal(SIGTSTP, SIG_IGN); | |
| 6886 | + signal(SIGTTOU, SIG_IGN); | |
| 6887 | + signal(SIGTTIN, SIG_IGN); | |
| 6888 | + } | |
| 6889 | +#endif | |
| 6890 | + | |
| 6833 | 6891 | #ifdef USE_KQEMU |
| 6834 | 6892 | if (smp_cpus > 1) |
| 6835 | 6893 | kqemu_allowed = 0; |
| ... | ... | @@ -7028,6 +7086,30 @@ int main(int argc, char **argv) |
| 7028 | 7086 | } |
| 7029 | 7087 | } |
| 7030 | 7088 | |
| 7089 | + if (daemonize) { | |
| 7090 | + uint8_t status = 0; | |
| 7091 | + ssize_t len; | |
| 7092 | + int fd; | |
| 7093 | + | |
| 7094 | + again1: | |
| 7095 | + len = write(fds[1], &status, 1); | |
| 7096 | + if (len == -1 && (errno == EINTR)) | |
| 7097 | + goto again1; | |
| 7098 | + | |
| 7099 | + if (len != 1) | |
| 7100 | + exit(1); | |
| 7101 | + | |
| 7102 | + fd = open("/dev/null", O_RDWR); | |
| 7103 | + if (fd == -1) | |
| 7104 | + exit(1); | |
| 7105 | + | |
| 7106 | + dup2(fd, 0); | |
| 7107 | + dup2(fd, 1); | |
| 7108 | + dup2(fd, 2); | |
| 7109 | + | |
| 7110 | + close(fd); | |
| 7111 | + } | |
| 7112 | + | |
| 7031 | 7113 | main_loop(); |
| 7032 | 7114 | quit_timers(); |
| 7033 | 7115 | return 0; | ... | ... |