summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRichard Jones <rjones@redhat.com>2009-11-03 15:30:36 +0000
committerRichard Jones <rjones@redhat.com>2009-11-03 15:31:20 +0000
commit08c9bf5e22ecf06e36cf128416a62214704da411 (patch)
tree82a3c08147494d3e72bf5ba44cf4223ab38e9042
parent90cf7fc904fca42665fe04cdd90a4c547d23b00c (diff)
downloadlibguestfs-08c9bf5e22ecf06e36cf128416a62214704da411.tar.gz
libguestfs-08c9bf5e22ecf06e36cf128416a62214704da411.tar.xz
libguestfs-08c9bf5e22ecf06e36cf128416a62214704da411.zip
Allow callers to disable the recovery process.
-rwxr-xr-xsrc/generator.ml26
-rw-r--r--src/guestfs.c71
2 files changed, 71 insertions, 26 deletions
diff --git a/src/generator.ml b/src/generator.ml
index bbdb3308..a06e208d 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -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
diff --git a/src/guestfs.c b/src/guestfs.c
index a25e9e77..f7df27e9 100644
--- a/src/guestfs.c
+++ b/src/guestfs.c
@@ -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);