[Crash-utility] [PATCH] Allows to change the error output direction

Dave Anderson anderson at redhat.com
Mon Jun 24 16:06:14 UTC 2019


----- Original Message -----
> Hi Dave,
> 
> Here I attach as a file for the patch. Thanks.
> 
> Kind regards,
> Daniel

Hi Daniel,

As I mentioned before, the concept seems reasonable, which I thought
was to allow a user to prevent error() messages from being intermingled
with command output by redirecting them somewhere else.  But that's 
apparently not the case, as a few simple examples show otherwise.  

Here's the default setting, and a sample command generating an error:

  crash> set -v
          scroll: on (/usr/bin/less)
           radix: 10 (decimal)
         refresh: on
       print_max: 256
     print_array: off
         console: (not assigned)
           debug: 0
            core: off
            hash: on
          silent: off
            edit: vi
        namelist: /usr/lib/debug/lib/modules/3.10.0-957.21.2.el7.x86_64/vmlinux
        dumpfile: (null)
          unwind: off
   zero_excluded: off
       null-stop: off
             gdb: off
           scope: 0 (not set)
         offline: show
         redzone: on
          stderr: stdout
  crash> bt 33333
  bt: invalid task or pid value: 33333
  crash>

Here I set stderr to /dev/null, which sets the new pc->stderr, 
but the behavior is still the same:

  crash> set stderr /dev/null
  stderr: /dev/null
  crash> set  -v
          scroll: on (/usr/bin/less)
           radix: 10 (decimal)
         refresh: on
       print_max: 256
     print_array: off
         console: (not assigned)
           debug: 0
            core: off
            hash: on
          silent: off
            edit: vi
        namelist: /usr/lib/debug/lib/modules/3.10.0-957.21.2.el7.x86_64/vmlinux
        dumpfile: (null)
          unwind: off
   zero_excluded: off
       null-stop: off
             gdb: off
           scope: 0 (not set)
         offline: show
         redzone: on
          stderr: /dev/null
  crash> bt 33333
  bt: invalid task or pid value: 33333
  crash>

Or if I set it to a file, the same thing happens:

  crash> set stderr /tmp/junk
  stderr: /tmp/junk
  crash> set -v
          scroll: on (/usr/bin/less)
           radix: 10 (decimal)
         refresh: on
       print_max: 256
     print_array: off
         console: (not assigned)
           debug: 0
            core: off
            hash: on
          silent: off
            edit: vi
        namelist: /usr/lib/debug/lib/modules/3.10.0-957.21.2.el7.x86_64/vmlinux
        dumpfile: (null)
          unwind: off
   zero_excluded: off
       null-stop: off
             gdb: off
           scope: 0 (not set)
         offline: show
         redzone: on
          stderr: /tmp/junk
  crash> bt 33333
  bt: invalid task or pid value: 33333
  crash> 
  
With your patch applied, the help page indicates:

 stderr  stdout | fp | <path>  set the direction of error put. 'stdout' always
                               print on console. 'fp' follows the redirection
                               or pipe command. '<path>' can be any file path
                               in the filesystem which can save the output

Is states that "<path>" can be any file path in the filesystem which can save
the output.  But even I redirect a command, it still doesn't seem to do what
it states:

  crash> set stderr /dev/null
  stderr: /dev/null
  crash> bt 33333 > /tmp/junk
  crash> !cat /tmp/junk
  bt: invalid task or pid value: 33333
  crash> 

Or if I pipe it:

  crash> bt 33333 | cat
  bt: invalid task or pid value: 33333
  crash>

What am I missing?
 
And also, a couple more things...

Please make pc->stderr_path a pointer:

  --- a/defs.h
  +++ b/defs.h
  @@ -553,6 +553,8 @@ struct program_context {
          ulong scope;                    /* optional text context address */
          ulong nr_hash_queues;           /* hash queue head count */
          char *(*read_vmcoreinfo)(const char *);
  +        FILE *stderr;                   /* error() message direction */
  +        char stderr_path[PATH_MAX];     /* stderr path information */
   };

Since it's typically going to contain a handful of bytes, it's kind of wasteful
to use PATH_MAX (4096).  Just use malloc/free to get a buffer of the correct
length.

And please display pc->stderr and pc->stderr_path to dump_program_context()
for use by "help -p".

Thanks,
  Dave





> 
> 
> On Sat, Jun 22, 2019 at 5:24 AM Dave Anderson < anderson at redhat.com > wrote:
> 
> 
> 
> Hi Daniel,
> 
> The idea seems reasonable, but the patch below is malformed:
> 
> $ patch -p1 < error.patch
> checking file defs.h
> Hunk #1 FAILED at 553.
> 1 out of 1 hunk FAILED
> checking file help.c
> patch: **** malformed patch at line 52: displayed by",
> 
> $
> 
> You can see that there are a quite a few unintended line wraps
> in the patch below.
> 
> Can you make the patch a discrete attachment to your email?
> 
> Thanks,
> Dave
> 
> 
> ----- Original Message -----
> > Currently, the error() is always printing the output to the console
> > through 'stdout'. This does not follow redirection which is good when
> > you want to know error while redirecting commands output to a file.
> > However, there are situations that you want to hide error messages or
> > redirect it into somewhere else.
> > 
> > Using 'set stderr' command, it can be changed to three different
> > destination - fixed 'stdout', following redirection (fp), or a custom
> > file path.
> > 
> > crash> set stderr
> > stderr: stdout
> > crash> sym 0x523 > /dev/null
> > sym: invalid address: 0x523
> > crash> set stderr fp
> > stderr: fp
> > crash> sym 0x523 > /dev/null
> > crash> set stderr /tmp/err.log
> > stderr: /tmp/err.log
> > crash> sym 0x523 > /dev/null
> > crash> set stderr stdout
> > stderr: stdout
> > crash> sym 0x523 > /dev/null
> > sym: invalid address: 0x523
> > ---
> > defs.h | 2 ++
> > help.c | 5 +++++
> > main.c | 2 ++
> > tools.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++++++---
> > 4 files changed, 61 insertions(+), 3 deletions(-)
> > 
> > diff --git a/defs.h b/defs.h
> > index ccffe58..57850c6 100644
> > --- a/defs.h
> > +++ b/defs.h
> > @@ -553,6 +553,8 @@ struct program_context {
> > ulong scope; /* optional text context address */
> > ulong nr_hash_queues; /* hash queue head count */
> > char *(*read_vmcoreinfo)(const char *);
> > + FILE *stderr; /* error() message direction */
> > + char stderr_path[PATH_MAX]; /* stderr path information */
> > };
> > 
> > #define READMEM pc->readmem
> > diff --git a/help.c b/help.c
> > index 581e616..ddc8e86 100644
> > --- a/help.c
> > +++ b/help.c
> > @@ -1093,6 +1093,10 @@ char *help_set[] = {
> > " redzone on | off if on, CONFIG_SLUB object addresses
> > displayed by",
> > " the kmem command will point to the
> > SLAB_RED_ZONE",
> > " padding inserted at the beginning of
> > the object.",
> > +" stderr stdout | fp | <path> set the direction of error put.
> > 'stdout' always",
> > +" print on console. 'fp' follows the
> > redirection",
> > +" or pipe command. '<path>' can be any
> > file path",
> > +" in the filesystem which can save the
> > output",
> > " ",
> > " Internal variables may be set in four manners:\n",
> > " 1. entering the set command in $HOME/.%src.",
> > @@ -1144,6 +1148,7 @@ char *help_set[] = {
> > " scope: (not set)",
> > " offline: show",
> > " redzone: on",
> > +" stderr: stdout",
> > " ",
> > " Show the current context:\n",
> > " %s> set",
> > diff --git a/main.c b/main.c
> > index 83ccd31..68bdec4 100644
> > --- a/main.c
> > +++ b/main.c
> > @@ -1085,6 +1085,8 @@ setup_environment(int argc, char **argv)
> > * to pipes or output files.
> > */
> > fp = stdout;
> > + pc->stderr = stdout;
> > + strcpy(pc->stderr_path, "stdout");
> > 
> > /*
> > * Start populating the program_context structure. It's used so
> > diff --git a/tools.c b/tools.c
> > index 2d95c3a..840d07c 100644
> > --- a/tools.c
> > +++ b/tools.c
> > @@ -58,6 +58,9 @@ __error(int type, char *fmt, ...)
> > void *retaddr[NUMBER_STACKFRAMES] = { 0 };
> > va_list ap;
> > 
> > + if (!strcmp(pc->stderr_path, "fp"))
> > + pc->stderr = fp;
> > +
> > if (CRASHDEBUG(1) || (pc->flags & DROP_CORE)) {
> > SAVE_RETURN_ADDRESS(retaddr);
> > console("error() trace: %lx => %lx => %lx => %lx\n",
> > @@ -69,7 +72,7 @@ __error(int type, char *fmt, ...)
> > va_end(ap);
> > 
> > if (!fmt && FATAL_ERROR(type)) {
> > - fprintf(stdout, "\n");
> > + fprintf(pc->stderr, "\n");
> > clean_exit(1);
> > }
> > 
> > @@ -95,14 +98,14 @@ __error(int type, char *fmt, ...)
> > buf);
> > fflush(pc->stdpipe);
> > } else {
> > - fprintf(stdout, "%s%s%s %s%s",
> > + fprintf(pc->stderr, "%s%s%s %s%s",
> > new_line || end_of_line ? "\n" : "",
> > type == WARNING ? "WARNING" :
> > type == NOTE ? "NOTE" :
> > type == CONT ? spacebuf : pc->curcmd,
> > type == CONT ? " " : ":",
> > buf, end_of_line ? "\n" : "");
> > - fflush(stdout);
> > + fflush(pc->stderr);
> > }
> > 
> > if ((fp != stdout) && (fp != pc->stdpipe) && (fp != pc->tmpfile)) {
> > @@ -2483,6 +2486,51 @@ cmd_set(void)
> > }
> > return;
> > 
> > + } else if (STREQ(args[optind], "stderr")) {
> > + if (args[optind+1]) {
> > + FILE *tmp_fp = NULL;
> > + char tmp_path[PATH_MAX];
> > +
> > + optind++;
> > + if (STREQ(args[optind], "stdout")) {
> > + tmp_fp = stdout;
> > + strcpy(tmp_path, "stdout");
> > + } else if (STREQ(args[optind], "fp")) {
> > + tmp_fp = fp;
> > + strcpy(tmp_path, "fp");
> > + } else {
> > + if (strlen(args[optind]) >=
> > PATH_MAX) {
> > + error(INFO, "path
> > length %d is too long. (max=%d)\n",
> > +
> > strlen(args[optind]), PATH_MAX);
> > + return;
> > + }
> > + tmp_fp = fopen(args[optind], "a");
> > + if (tmp_fp != NULL) {
> > + strcpy(tmp_path,
> > args[optind]);
> > + } else {
> > + error(INFO, "invalid
> > path: %s\n",
> > + args[optind]);
> > + return;
> > + }
> > +
> > + }
> > +
> > + if (strcmp(pc->stderr_path, tmp_path)) {
> > + if (strcmp(pc->stderr_path,
> > "stdout")
> > + && strcmp(pc->stderr_path,
> > "fp")) {
> > + fclose(pc->stderr);
> > + }
> > + pc->stderr = tmp_fp;
> > + strcpy(pc->stderr_path, tmp_path);
> > + }
> > + }
> > +
> > + if (runtime) {
> > + fprintf(fp, "stderr: %s\n",
> > + pc->stderr_path);
> > + }
> > + return;
> > +
> > } else if (XEN_HYPER_MODE()) {
> > error(FATAL, "invalid argument for the Xen hypervisor\n");
> > } else if (pc->flags & MINIMAL_MODE) {
> > @@ -2590,6 +2638,7 @@ show_options(void)
> > fprintf(fp, "(not set)\n");
> > fprintf(fp, " offline: %s\n", pc->flags2 & OFFLINE_HIDE ?
> > "hide" : "show");
> > fprintf(fp, " redzone: %s\n", pc->flags2 & REDZONE ? "on" : "off");
> > + fprintf(fp, " stderr: %s\n", pc->stderr_path);
> > }
> > 
> > 
> > --
> > 1.8.3.1
> > 
> > --
> > Crash-utility mailing list
> > Crash-utility at redhat.com
> > https://www.redhat.com/mailman/listinfo/crash-utility
> > 
> 
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
> 
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility




More information about the Crash-utility mailing list