]> git.proxmox.com Git - mirror_qemu.git/commitdiff
Daemonize option, by Anthony Liguori.
authorths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 22 Dec 2006 02:11:31 +0000 (02:11 +0000)
committerths <ths@c046a42c-6fe2-441c-8c8c-71466251a162>
Fri, 22 Dec 2006 02:11:31 +0000 (02:11 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2261 c046a42c-6fe2-441c-8c8c-71466251a162

qemu-doc.texi
vl.c

index ea4d2e63a4c9f918c412db93497c87c82d2a2df9..6796aeb6d36e986177c89d04fcbc843437c94c65 100644 (file)
@@ -309,6 +309,12 @@ Start in full screen.
 Store the QEMU process PID in @var{file}. It is useful if you launch QEMU
 from a script.
 
+@item -daemonize
+Daemonize the QEMU process after initialization.  QEMU will not detach from
+standard IO until it is ready to receive connections on any of its devices.
+This option is a useful way for external programs to launch QEMU without having
+to cope with initialization race conditions.
+
 @item -win2k-hack
 Use it when installing Windows 2000 to avoid a disk full bug. After
 Windows 2000 is installed, you no longer need this option (this option
diff --git a/vl.c b/vl.c
index 929d2a938c463ad825406cafcf66d354f9e164a3..c56c87cfe6825437828c98e6d3a2bb736c926f78 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -163,6 +163,7 @@ const char *vnc_display;
 int acpi_enabled = 1;
 int fd_bootchk = 1;
 int no_reboot = 0;
+int daemonize = 0;
 
 /***********************************************************/
 /* x86 ISA bus support */
@@ -6018,6 +6019,9 @@ void help(void)
            "-no-reboot      exit instead of rebooting\n"
            "-loadvm file    start right away with a saved state (loadvm in monitor)\n"
           "-vnc display    start a VNC server on display\n"
+#ifndef _WIN32
+          "-daemonize      daemonize QEMU after initializing\n"
+#endif
            "\n"
            "During emulation, the following keys are useful:\n"
            "ctrl-alt-f      toggle full screen\n"
@@ -6098,6 +6102,7 @@ enum {
     QEMU_OPTION_vnc,
     QEMU_OPTION_no_acpi,
     QEMU_OPTION_no_reboot,
+    QEMU_OPTION_daemonize,
 };
 
 typedef struct QEMUOption {
@@ -6178,6 +6183,7 @@ const QEMUOption qemu_options[] = {
     { "cirrusvga", 0, QEMU_OPTION_cirrusvga },
     { "no-acpi", 0, QEMU_OPTION_no_acpi },
     { "no-reboot", 0, QEMU_OPTION_no_reboot },
+    { "daemonize", 0, QEMU_OPTION_daemonize },
     { NULL },
 };
 
@@ -6408,6 +6414,7 @@ int main(int argc, char **argv)
     QEMUMachine *machine;
     char usb_devices[MAX_USB_CMDLINE][128];
     int usb_devices_index;
+    int fds[2];
 
     LIST_INIT (&vm_change_state_head);
 #ifndef _WIN32
@@ -6826,10 +6833,61 @@ int main(int argc, char **argv)
             case QEMU_OPTION_no_reboot:
                 no_reboot = 1;
                 break;
+           case QEMU_OPTION_daemonize:
+               daemonize = 1;
+               break;
             }
         }
     }
 
+#ifndef _WIN32
+    if (daemonize && !nographic && vnc_display == NULL) {
+       fprintf(stderr, "Can only daemonize if using -nographic or -vnc\n");
+       daemonize = 0;
+    }
+
+    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 || status != 0)
+               exit(1);
+           else
+               exit(0);
+       } else if (pid < 0)
+           exit(1);
+
+       setsid();
+
+       pid = fork();
+       if (pid > 0)
+           exit(0);
+       else if (pid < 0)
+           exit(1);
+
+       umask(027);
+       chdir("/");
+
+        signal(SIGTSTP, SIG_IGN);
+        signal(SIGTTOU, SIG_IGN);
+        signal(SIGTTIN, SIG_IGN);
+    }
+#endif
+
 #ifdef USE_KQEMU
     if (smp_cpus > 1)
         kqemu_allowed = 0;
@@ -7028,6 +7086,30 @@ int main(int argc, char **argv)
         }
     }
 
+    if (daemonize) {
+       uint8_t status = 0;
+       ssize_t len;
+       int fd;
+
+    again1:
+       len = write(fds[1], &status, 1);
+       if (len == -1 && (errno == EINTR))
+           goto again1;
+
+       if (len != 1)
+           exit(1);
+
+       fd = open("/dev/null", O_RDWR);
+       if (fd == -1)
+           exit(1);
+
+       dup2(fd, 0);
+       dup2(fd, 1);
+       dup2(fd, 2);
+
+       close(fd);
+    }
+
     main_loop();
     quit_timers();
     return 0;