[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]

[Libguestfs] [PATCH v2] Enable coredumps to be captured from the appliance (RHBZ#619334).



The last version omitted to implement LIBGUESTFS_COREDUMP.  This
fixes that ...

Rich.

-- 
Richard Jones, Virtualization Group, Red Hat http://people.redhat.com/~rjones
New in Fedora 11: Fedora Windows cross-compiler. Compile Windows
programs, test, and build Windows installers. Over 70 libraries supprt'd
http://fedoraproject.org/wiki/MinGW http://www.annexia.org/fedora_mingw
>From 927fce62f13bf2201bc93e2cba88334a383268e5 Mon Sep 17 00:00:00 2001
From: Richard Jones <rjones redhat com>
Date: Sat, 31 Jul 2010 14:35:32 +0100
Subject: [PATCH] Enable coredumps to be captured from the appliance (RHBZ#619334).

---
 daemon/guestfsd.c      |   45 ++++++++++++++++++++++++++++++
 fish/guestfish.pod     |    6 ++++
 src/generator.ml       |   72 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/guestfs-internal.h |    1 +
 src/guestfs.c          |   36 ++++++++++++++++++++++++
 src/guestfs.pod        |    6 ++++
 src/launch.c           |    8 +++++
 7 files changed, 174 insertions(+), 0 deletions(-)

diff --git a/daemon/guestfsd.c b/daemon/guestfsd.c
index 49aca08..91d59cc 100644
--- a/daemon/guestfsd.c
+++ b/daemon/guestfsd.c
@@ -42,6 +42,8 @@
 #include <arpa/inet.h>
 #include <netinet/in.h>
 #include <errno.h>
+#include <sys/time.h>
+#include <sys/resource.h>
 
 #ifdef HAVE_PRINTF_H
 # include <printf.h>
@@ -211,6 +213,49 @@ main (int argc, char *argv[])
   }
 
 #ifndef WIN32
+  /* Enable coredumps. */
+  if (cmdline) {
+    char *p = strstr (cmdline, "guestfs_coredump=");
+    if (p) {
+      p += 17;
+      size_t len = strcspn (p, " \t\n");
+      char *coredump = strndup (p, len);
+      if (!coredump) {
+        perror ("strndup");
+        exit (EXIT_FAILURE);
+      }
+
+#define CORE_PATTERN "/proc/sys/kernel/core_pattern"
+      int fd = open (CORE_PATTERN, O_WRONLY);
+      if (fd == -1) {
+        perror ("open: " CORE_PATTERN);
+        exit (EXIT_FAILURE);
+      }
+      if (write (fd, coredump, len) < (ssize_t) len) {
+        perror ("write: " CORE_PATTERN);
+        exit (EXIT_FAILURE);
+      }
+      if (close (fd) == -1) {
+        perror ("close: " CORE_PATTERN);
+        exit (EXIT_FAILURE);
+      }
+
+      struct rlimit limit = {
+        .rlim_cur = RLIM_INFINITY,
+        .rlim_max = RLIM_INFINITY
+      };
+      if (setrlimit (RLIMIT_CORE, &limit) == -1) {
+        perror ("setrlimit (RLIMIT_CORE)");
+        exit (EXIT_FAILURE);
+      }
+
+      if (verbose)
+        printf ("coredumps enabled to '%s'\n", coredump);
+    }
+  }
+#endif /* !WIN32 */
+
+#ifndef WIN32
   /* Make sure SIGPIPE doesn't kill us. */
   struct sigaction sa;
   memset (&sa, 0, sizeof sa);
diff --git a/fish/guestfish.pod b/fish/guestfish.pod
index bfcec5c..9aa01df 100644
--- a/fish/guestfish.pod
+++ b/fish/guestfish.pod
@@ -875,6 +875,12 @@ home directory can be used.  See L</FILES>.
 
 Pass additional options to the guest kernel.
 
+=item LIBGUESTFS_COREDUMP
+
+Capture coredump(s) which happen inside the libguestfs appliance.
+For further details of this option, see
+L<guestfs(3)/guestfs_set_coredump>.
+
 =item LIBGUESTFS_DEBUG
 
 Set C<LIBGUESTFS_DEBUG=1> to enable verbose messages.  This has the
diff --git a/src/generator.ml b/src/generator.ml
index 52e7aba..fea771a 100755
--- a/src/generator.ml
+++ b/src/generator.ml
@@ -940,6 +940,78 @@ to specify the QEMU interface emulation to use at run time.");
 This is the same as C<guestfs_add_drive_ro> but it allows you
 to specify the QEMU interface emulation to use at run time.");
 
+  ("set_coredump", (RErr, [OptString "coredump"]), -1, [FishAlias "coredump"],
+   [],
+   "capture coredump to file or block device",
+   "\
+This option can be used to debug coredumps in the libguestfs
+appliance, in the daemon or in auxiliary programs that it
+runs.  Set this to a string which is written verbatim to
+C</proc/sys/kernel/core_pattern> in the appliance during launch.
+Set this to NULL to disable coredumps.
+
+Useful values for this setting include:
+
+=over 4
+
+=item C</sysroot/core.%t.%p.%e>
+
+Coredump(s) are written to the root directory of the mounted
+guest disk.  The name of the core file includes the current
+time (seconds since the epoch), PID, and the name of the
+executable.
+
+Note that the prefix C</sysroot> is an implementation detail
+of the current appliance and may change in future.
+
+This requires that a guest disk is mounted and writable
+at the time that the coredump is generated, otherwise
+the coredump will be discarded.
+
+=back
+
+The following are I<not> useful values for this setting:
+
+=over 4
+
+=item C</dev/vdb>
+
+The Linux kernel explicitly disallows writing coredumps to
+non-regular files.  Therefore using a coredump capture device
+like this does not work.
+
+=item C</tmp/core>
+
+=item C<filename>
+
+If you use paths or filenames like these, then coredump(s) are written
+to the root disk in the appliance.  This is not very useful, because
+the root disk is a ramdisk which is forgotten when the appliance
+shuts down.
+
+=back
+
+The default is C<NULL> unless overridden by setting the
+C<LIBGUESTFS_COREDUMP> environment variable.
+
+Note that you must set this before calling C<guestfs_launch>,
+otherwise it has no effect.
+
+This debugging feature is not part of the ABI and may be
+changed or removed in a future release.");
+
+  ("get_coredump", (RConstOptString "coredump", []), -1, [],
+   (* This cannot be tested with the current framework.  The
+    * function can return NULL in normal operations, which the
+    * test framework interprets as an error.
+    *)
+   [],
+   "get the coredump debugging setting",
+   "\
+Return the coredump debugging setting.
+
+See C<guestfs_set_coredump>.");
+
 ]
 
 (* daemon_functions are any functions which cause some action
diff --git a/src/guestfs-internal.h b/src/guestfs-internal.h
index 12ca0ec..9f90904 100644
--- a/src/guestfs-internal.h
+++ b/src/guestfs-internal.h
@@ -110,6 +110,7 @@ struct guestfs_h
   char *path;			/* Path to kernel, initrd. */
   char *qemu;			/* Qemu binary. */
   char *append;			/* Append to kernel command line. */
+  char *coredump;               /* Coredump path. */
 
   int memsize;			/* Size of RAM (megabytes). */
 
diff --git a/src/guestfs.c b/src/guestfs.c
index c54462d..10dd1e4 100644
--- a/src/guestfs.c
+++ b/src/guestfs.c
@@ -120,6 +120,12 @@ guestfs_create (void)
     if (!g->append) goto error;
   }
 
+  str = getenv ("LIBGUESTFS_COREDUMP");
+  if (str) {
+    g->coredump = strdup (str);
+    if (!g->coredump) goto error;
+  }
+
   /* Choose a suitable memory size.  Previously we tried to choose
    * a minimal memory size, but this isn't really necessary since
    * recent QEMU and KVM don't do anything nasty like locking
@@ -160,6 +166,7 @@ guestfs_create (void)
   free (g->path);
   free (g->qemu);
   free (g->append);
+  free (g->coredump);
   free (g);
   return NULL;
 }
@@ -509,6 +516,35 @@ guestfs__get_append (guestfs_h *g)
 }
 
 int
+guestfs__set_coredump (guestfs_h *g, const char *coredump)
+{
+  if (coredump != NULL) {
+    /* Because we pass this in the kernel command line, it will
+     * currently fail if it contains any whitespace.  We ought to fix
+     * this by escaping spaces and unescaping them in the appliance. XXX
+     */
+    size_t i;
+    for (i = 0; i < strlen (coredump); ++i)
+      if (c_isspace (coredump[i])) {
+        error (g, "coredump parameter must not contain whitespace");
+        return -1;
+      }
+  }
+
+  free (g->coredump);
+  g->coredump = NULL;
+
+  g->coredump = coredump ? safe_strdup (g, coredump) : NULL;
+  return 0;
+}
+
+const char *
+guestfs__get_coredump (guestfs_h *g)
+{
+  return g->coredump;
+}
+
+int
 guestfs__set_memsize (guestfs_h *g, int memsize)
 {
   g->memsize = memsize;
diff --git a/src/guestfs.pod b/src/guestfs.pod
index 5a2e7a5..0749da7 100644
--- a/src/guestfs.pod
+++ b/src/guestfs.pod
@@ -1478,6 +1478,12 @@ time.
 
 Pass additional options to the guest kernel.
 
+=item LIBGUESTFS_COREDUMP
+
+Capture coredump(s) which happen inside the libguestfs appliance.
+For further details of this option, see
+L</guestfs_set_coredump>.
+
 =item LIBGUESTFS_DEBUG
 
 Set C<LIBGUESTFS_DEBUG=1> to enable verbose messages.  This
diff --git a/src/launch.c b/src/launch.c
index 0d7a3f3..5d3c236 100644
--- a/src/launch.c
+++ b/src/launch.c
@@ -598,6 +598,12 @@ guestfs__launch (guestfs_h *g)
     add_cmdline (g, "-net");
     add_cmdline (g, "nic,model=" NET_IF ",vlan=0");
 
+    /* Coredump parameter for Linux command line. */
+    size_t len = g->coredump ? 32 + strlen (g->coredump) : 0;
+    char coredump[len];
+    if (g->coredump)
+      snprintf (coredump, len, "guestfs_coredump=%s", g->coredump);
+
 #define LINUX_CMDLINE							\
     "panic=1 "         /* force kernel to panic if daemon exits */	\
     "console=ttyS0 "   /* serial console */				\
@@ -613,11 +619,13 @@ guestfs__launch (guestfs_h *g)
               "%s "             /* (selinux) */
               "%s "             /* (vmchannel) */
               "%s "             /* (verbose) */
+              "%s "             /* (coredump) */
               "TERM=%s "        /* (TERM environment variable) */
               "%s",             /* (append) */
               g->selinux ? "selinux=1 enforcing=0" : "selinux=0",
               vmchannel ? vmchannel : "",
               g->verbose ? "guestfs_verbose=1" : "",
+              g->coredump ? coredump : "",
               getenv ("TERM") ? : "linux",
               g->append ? g->append : "");
 
-- 
1.7.1


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]