commit-hurd
[Top][All Lists]
Advanced

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

[hurd] 19/19: trans/crash: core file name templates


From: Samuel Thibault
Subject: [hurd] 19/19: trans/crash: core file name templates
Date: Wed, 10 Aug 2016 00:05:51 +0000

This is an automated email from the git hooks/post-receive script.

sthibault pushed a commit to branch upstream
in repository hurd.

commit 02f5c0208985d60fede08c1eafad04e80353b670
Author: Justus Winter <address@hidden>
Date:   Fri Jun 3 00:52:06 2016 +0200

    trans/crash: core file name templates
    
    Add an option to specify a template used to construct core file names.
    This way core files can be collected at a predictable central
    location.
    
    * hurd/crash.defs (crash_dump_task): Return EEXIST if the core file
    has been written elsewhere.
    * trans/crash.c (corefile_template): New variable.
    (template_valid): New function.
    (template_make_file_name): Likewise.
    (S_crash_dump_task): Use the template to construct a name, open the
    file, and write the core dump there instead of the handle provided by
    the caller.
    (argp_option): New option.
    (doc): Document the format.
    (parse_opt): Handle new option
    (trivfs_append_args): Likewise.
---
 hurd/crash.defs |   6 +-
 trans/crash.c   | 166 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 2 files changed, 168 insertions(+), 4 deletions(-)

diff --git a/hurd/crash.defs b/hurd/crash.defs
index 442957d..4295861 100644
--- a/hurd/crash.defs
+++ b/hurd/crash.defs
@@ -25,8 +25,10 @@ subsystem crash 32000;
 
 /* Handle a crashing task, whose task control port is TASK.
 
-   FILE is a file port open for writing.  The caller will link it to "core"
-   (or whatever name) if the RPC returns success.
+   FILE is a file port open for writing.  The caller will link it to
+   "core" (or whatever name) if the RPC returns success.  If EEXIST is
+   returned, the core file has been written to a different file,
+   therefore FILE can be discarded.
 
    SIGNO, SIGCODE, and SIGERROR indicate the signal that killed the
    process.  EXC is zero for a software signal; otherwise EXC, CODE, and
diff --git a/trans/crash.c b/trans/crash.c
index 058d15e..14783cf 100644
--- a/trans/crash.c
+++ b/trans/crash.c
@@ -70,7 +70,105 @@ enum crash_action
 #define CRASH_ORPHANS_DEFAULT  crash_corefile
 
 static enum crash_action crash_how, crash_orphans_how;
+static char *corefile_template;
 
+
+
+/* Template parsing.  */
+static int
+template_valid (const char *template, const char **errp)
+{
+  int valid = 0;
+  const char *t;
+  int specifier = 0;
+
+  for (t = template; *t; t++)
+    {
+      if (specifier)
+       switch (*t)
+         {
+         case '%':
+         case 'p':
+         case 's':
+         case 't':
+           specifier = 0;
+           break;
+         default:
+           goto out;
+         }
+      else if (*t == '%')
+       specifier = 1;
+    }
+
+ out:
+  valid = ! specifier;
+  *errp = valid? NULL: t;
+  return valid;
+}
+
+static char *
+template_make_file_name (const char *template,
+                        task_t task,
+                        int signo)
+{
+  const char *t;
+  char *file_name = NULL;
+  size_t file_name_len = 0;
+  FILE *stream;
+  int specifier = 0;
+
+  if (! template_valid (template, &t))
+    {
+      errno = EINVAL;
+      return NULL;
+    }
+
+  stream = open_memstream (&file_name, &file_name_len);
+  if (stream == NULL)
+    return NULL;
+
+  for (t = template; *t; t++)
+    {
+      if (specifier)
+       {
+         switch (*t)
+           {
+           case '%':
+             fprintf (stream, "%%");
+             break;
+
+           case 'p':
+             fprintf (stream, "%d", task2pid (task));
+             break;
+
+           case 's':
+             fprintf (stream, "%d", signo);
+             break;
+
+           case 't':
+             fprintf (stream, "%d", time (NULL));
+             break;
+
+           default:
+             assert (!"reached!");
+           }
+         specifier = 0;
+       }
+      else if (*t == '%')
+       specifier = 1;
+      else
+       fprintf (stream, "%c", *t);
+    }
+
+  assert (! specifier);
+
+  fprintf (stream, "%c", 0);
+  fclose (stream);
+
+  return file_name;
+}
+
+
 
 /* This is defined in ../exec/elfcore.c, or we could have
    different implementations for other formats.  */
@@ -237,10 +335,42 @@ S_crash_dump_task (mach_port_t port,
       err = task_suspend (task);
       if (!err)
        {
-         err = dump_core (task, core_file,
+         file_t sink = core_file;
+         if (corefile_template)
+           {
+             char *file_name;
+
+             file_name = template_make_file_name (corefile_template,
+                                                  task, signo);
+             if (file_name == NULL)
+               error (0, errno, "template_make_file_name");
+             else
+               {
+                 sink = file_name_lookup (file_name, O_WRONLY|O_CREAT,
+                                          S_IRUSR);
+                 if (! MACH_PORT_VALID (sink))
+                   {
+                     error (0, errno, "%s", file_name);
+                     sink = core_file;
+                   }
+                 free (file_name);
+               }
+           }
+
+         err = dump_core (task, sink,
                           (off_t) -1,  /* XXX should get core limit in RPC */
                           signo, sigcode, sigerror);
          task_resume (task);
+
+         if (sink != core_file)
+           {
+             mach_port_deallocate (mach_task_self (), sink);
+
+             /* We return an error so that the libc discards
+                CORE_FILE.  */
+             if (! err)
+               err = EEXIST;
+           }
        }
       break;
 
@@ -450,13 +580,25 @@ static const struct argp_option options[] =
   {"kill",     'k', 0,         0, "Kill the process", 2},
   {"core-file", 'c', 0,                0, "Dump a core file", 2},
   {"dump-core",   0, 0,                OPTION_ALIAS },
+  {"core-file-name", 'C', "TEMPLATE", 0,
+   "Specify core file name (see below)", 2},
   {0}
 };
 static const char doc[] =
 "Server to handle crashing tasks and dump core files or equivalent.\v"
 "The ACTION values can be `suspend', `kill', or `core-file'.\n\n"
 "If `--orphan-action' is not specified, the `--action' value is used for "
-"orphans.  The default is `--action=suspend --orphan-action=core-file'.";
+"orphans.  The default is `--action=suspend --orphan-action=core-file'.\n"
+"\n"
+"The core file is either written to the file provided by the "
+"crashing process, or if a TEMPLATE value is given, to the file "
+"with the name constructed by expanding TEMPLATE value.  "
+"TEMPLATE may contain % specifiers:\n"
+"\n"
+"\t%%  just %\n"
+"\t%p  the process' PID\n"
+"\t%s  the signal number that caused the dump\n"
+"\t%t  time of crash in seconds since the EPOCH\n";
 
 static error_t
 parse_opt (int opt, char *arg, struct argp_state *state)
@@ -494,6 +636,14 @@ parse_opt (int opt, char *arg, struct argp_state *state)
     case 's': crash_how = crash_suspend;       break;
     case 'k': crash_how = crash_kill;          break;
     case 'c': crash_how = crash_corefile;      break;
+    case 'C':
+      {
+       char *errp;
+       if (! template_valid (arg, &errp))
+         error (1, 0, "Invalid template: ...'%s'", errp);
+      }
+      corefile_template = arg;
+      break;
 
     case ARGP_KEY_SUCCESS:
       if (crash_orphans_how == crash_unspecified)
@@ -536,6 +686,18 @@ trivfs_append_args (struct trivfs_control *fsys,
       err = argz_add (argz, argz_len, opt);
     }
 
+  if (!err && corefile_template)
+    {
+      char *template;
+      if (asprintf (&template, "--core-file-name=%s", corefile_template) < 0)
+       err = errno;
+      else
+       {
+         err = argz_add (argz, argz_len, template);
+         free (template);
+       }
+    }
+
   return err;
 }
 

-- 
Alioth's /usr/local/bin/git-commit-notice on 
/srv/git.debian.org/git/pkg-hurd/hurd.git



reply via email to

[Prev in Thread] Current Thread [Next in Thread]