Allow callers to disable the recovery process.
authorRichard Jones <rjones@redhat.com>
Tue, 3 Nov 2009 15:30:36 +0000 (15:30 +0000)
committerRichard Jones <rjones@redhat.com>
Tue, 3 Nov 2009 15:31:20 +0000 (15:31 +0000)
src/generator.ml
src/guestfs.c

index bbdb330..a06e208 100755 (executable)
@@ -835,6 +835,32 @@ The default is disabled.");
    "\
 Return the direct appliance mode flag.");
 
+  ("set_recovery_proc", (RErr, [Bool "recoveryproc"]), -1, [FishAlias "recovery-proc"],
+   [InitNone, Always, TestOutputTrue (
+      [["set_recovery_proc"; "true"];
+       ["get_recovery_proc"]])],
+   "enable or disable the recovery process",
+   "\
+If this is called with the parameter C<false> then
+C<guestfs_launch> does not create a recovery process.  The
+purpose of the recovery process is to stop runaway qemu
+processes in the case where the main program aborts abruptly.
+
+This only has any effect if called before C<guestfs_launch>,
+and the default is true.
+
+About the only time when you would want to disable this is
+if the main process will fork itself into the background
+(\"daemonize\" itself).  In this case the recovery process
+thinks that the main program has disappeared and so kills
+qemu, which is not very helpful.");
+
+  ("get_recovery_proc", (RBool "recoveryproc", []), -1, [],
+   [],
+   "get recovery process enabled flag",
+   "\
+Return the recovery process enabled flag.");
+
 ]
 
 (* daemon_functions are any functions which cause some action
index a25e9e7..f7df27e 100644 (file)
@@ -120,6 +120,7 @@ struct guestfs_h
   int trace;
   int autosync;
   int direct;
+  int recovery_proc;
 
   char *path;                  /* Path to kernel, initrd. */
   char *qemu;                  /* Qemu binary. */
@@ -169,6 +170,8 @@ guestfs_create (void)
   g->error_cb = default_error_cb;
   g->error_cb_data = NULL;
 
+  g->recovery_proc = 1;
+
   str = getenv ("LIBGUESTFS_DEBUG");
   g->verbose = str != NULL && strcmp (str, "1") == 0;
 
@@ -665,6 +668,19 @@ guestfs__get_direct (guestfs_h *g)
   return g->direct;
 }
 
+int
+guestfs__set_recovery_proc (guestfs_h *g, int f)
+{
+  g->recovery_proc = !!f;
+  return 0;
+}
+
+int
+guestfs__get_recovery_proc (guestfs_h *g)
+{
+  return g->recovery_proc;
+}
+
 /* Add a string to the current command line. */
 static void
 incr_cmdline_size (guestfs_h *g)
@@ -1213,36 +1229,39 @@ guestfs__launch (guestfs_h *g)
   /* Fork the recovery process off which will kill qemu if the parent
    * process fails to do so (eg. if the parent segfaults).
    */
-  r = fork ();
-  if (r == 0) {
-    pid_t qemu_pid = g->pid;
-    pid_t parent_pid = getppid ();
-
-    /* Writing to argv is hideously complicated and error prone.  See:
-     * http://anoncvs.postgresql.org/cvsweb.cgi/pgsql/src/backend/utils/misc/ps_status.c?rev=1.33.2.1;content-type=text%2Fplain
-     */
+  g->recoverypid = -1;
+  if (g->recovery_proc) {
+    r = fork ();
+    if (r == 0) {
+      pid_t qemu_pid = g->pid;
+      pid_t parent_pid = getppid ();
+
+      /* Writing to argv is hideously complicated and error prone.  See:
+       * http://anoncvs.postgresql.org/cvsweb.cgi/pgsql/src/backend/utils/misc/ps_status.c?rev=1.33.2.1;content-type=text%2Fplain
+       */
 
-    /* Loop around waiting for one or both of the other processes to
-     * disappear.  It's fair to say this is very hairy.  The PIDs that
-     * we are looking at might be reused by another process.  We are
-     * effectively polling.  Is the cure worse than the disease?
-     */
-    for (;;) {
-      if (kill (qemu_pid, 0) == -1) /* qemu's gone away, we aren't needed */
-        _exit (0);
-      if (kill (parent_pid, 0) == -1) {
-        /* Parent's gone away, qemu still around, so kill qemu. */
-        kill (qemu_pid, 9);
-        _exit (0);
+      /* Loop around waiting for one or both of the other processes to
+       * disappear.  It's fair to say this is very hairy.  The PIDs that
+       * we are looking at might be reused by another process.  We are
+       * effectively polling.  Is the cure worse than the disease?
+       */
+      for (;;) {
+        if (kill (qemu_pid, 0) == -1) /* qemu's gone away, we aren't needed */
+          _exit (0);
+        if (kill (parent_pid, 0) == -1) {
+          /* Parent's gone away, qemu still around, so kill qemu. */
+          kill (qemu_pid, 9);
+          _exit (0);
+        }
+        sleep (2);
       }
-      sleep (2);
     }
-  }
 
-  /* Don't worry, if the fork failed, this will be -1.  The recovery
-   * process isn't essential.
-   */
-  g->recoverypid = r;
+    /* Don't worry, if the fork failed, this will be -1.  The recovery
+     * process isn't essential.
+     */
+    g->recoverypid = r;
+  }
 
   /* Start the clock ... */
   time (&g->start_t);