bug-glibc
[Top][All Lists]
Advanced

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

Bug in module "misc/syslog.c" of glibc-2.3.1


From: Achim Gsell
Subject: Bug in module "misc/syslog.c" of glibc-2.3.1
Date: Thu, 13 Feb 2003 21:30:37 +0100
User-agent: KMail/1.5

Hi,

today we discussed an odd behavior of the syslog(3) function on the syslog-ng 
mailing list. If syslog-ng opens "/dev/log" as a UNIX_DGRAM socket everything 
works fine. But if syslog-ng opens "/dev/log" as a UNIX_STREAM socket 
messages may be lost after a restart of the daemon. A strace of the program

#include <syslog.h>

int main( int argc, char *argv[] ) {
  int cnt=0;

  openlog( argv[0], LOG_NDELAY|LOG_PID, LOG_DAEMON );

  while( 1 ) {
    syslog( LOG_INFO, "%d", ++cnt );
    sleep( 5 );
  }

  return( 0 );
}

reveals the problem:

rt_sigaction(SIGPIPE, {0x804d8d0, [], 0x4000000}, {SIG_DFL}, 8) = 0
send(3, "<30>Feb 13 21:04:15 ./syslog_tes"..., 44, 0) = -1 EPIPE (Broken pipe)
--- SIGPIPE (Broken pipe) ---
close(3)                                = 0
sigreturn()                             = ? (mask now [RTMIN])
rt_sigaction(SIGPIPE, {SIG_DFL}, NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, [CHLD], [RTMIN], 8) = 0
rt_sigaction(SIGCHLD, NULL, {SIG_DFL}, 8) = 0
rt_sigprocmask(SIG_SETMASK, [RTMIN], NULL, 8) = 0
nanosleep({5, 0},  <unfinished ...>

Lets take a look into the source:

        if (!connected || __send(LogFile, buf, bufsize, 0) < 0)
          {
            if (connected)
              {
                /* Try to reopen the syslog connection.  Maybe it went
                   down.  */
                closelog_internal ();
                openlog_internal(LogTag, LogStat | LOG_NDELAY, 0);
              }

            if (!connected || __send(LogFile, buf, bufsize, 0) < 0)
              {
                closelog_internal ();   /* attempt re-open next time */
                /*
                 * Output the message to the console; don't worry
                 * about blocking, if console blocks everything will.
                 * Make sure the error reported is the one from the
                 * syslogd failure.
                 */
                if (LogStat & LOG_CONS &&
                    (fd = __open(_PATH_CONSOLE, O_WRONLY|O_NOCTTY, 0)) >= 0)
                  {
                    dprintf (fd, "%s\r\n", buf + msgoff);
                    (void)__close(fd);
                  }
              }
          }

        if (sigpipe == 0)
                __sigaction (SIGPIPE, &oldaction, (struct sigaction *) NULL);

If we are connected and __send() returns with an error, there should be a 
connect(2) and a second send(2) in the strace output. But they aren't. The 
reason is that __send() returns with a value >= 0 even if send(2) returns 
with -1. The "sigpipe_handler()" seems to be non-reentrant! I removed the 
"closelog_internal ()" - in my opinion it's unnecessary - from the handler 
and everythings works fine.

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- syslog.c.orig       2003-02-13 19:49:44.000000000 +0100
+++ syslog.c    2003-02-13 21:25:15.000000000 +0100
@@ -351,7 +351,6 @@
 static void
 sigpipe_handler (int signo)
 {
-  closelog_internal ();
 }

 static void
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Best regards

Achim Gsell





reply via email to

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