How can a Unix program display output on screen even when stdout and stderr are redirected?

后端 未结 3 1595
半阙折子戏
半阙折子戏 2021-01-07 21:51

I was running a program (valgrind, actually) on my Ubuntu machine, and had redirected both stdout and stderr to different files. I was surprised to see a short message appea

3条回答
  •  北海茫月
    2021-01-07 22:16

    It is not written by valgrind but rather glibc and your ./myprogram is using glibc:

    #define _PATH_TTY   "/dev/tty"
    
    /* Open a descriptor for /dev/tty unless the user explicitly
       requests errors on standard error.  */
    const char *on_2 = __libc_secure_getenv ("LIBC_FATAL_STDERR_");
    if (on_2 == NULL || *on_2 == '\0')
      fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY);
    
    if (fd == -1)
      fd = STDERR_FILENO;
    
    ...
    written = WRITEV_FOR_FATAL (fd, iov, nlist, total);
    

    Below are some relevant parts of glibc:

    void
    __attribute__ ((noreturn))
    __stack_chk_fail (void)
    {
      __fortify_fail ("stack smashing detected");
    }
    
    void
    __attribute__ ((noreturn))
    __fortify_fail (msg)
         const char *msg;
    {
      /* The loop is added only to keep gcc happy.  */
      while (1)
        __libc_message (2, "*** %s ***: %s terminated\n",
                msg, __libc_argv[0] ?: "");
    }
    
    
    /* Abort with an error message.  */
    void
    __libc_message (int do_abort, const char *fmt, ...)
    {
      va_list ap;
      int fd = -1;
    
      va_start (ap, fmt);
    
    #ifdef FATAL_PREPARE
      FATAL_PREPARE;
    #endif
    
      /* Open a descriptor for /dev/tty unless the user explicitly
         requests errors on standard error.  */
      const char *on_2 = __libc_secure_getenv ("LIBC_FATAL_STDERR_");
      if (on_2 == NULL || *on_2 == '\0')
        fd = open_not_cancel_2 (_PATH_TTY, O_RDWR | O_NOCTTY | O_NDELAY);
    
      if (fd == -1)
        fd = STDERR_FILENO;
    
      ...
      written = WRITEV_FOR_FATAL (fd, iov, nlist, total);
    

提交回复
热议问题