This is the mail archive of the
libc-hacker@cygnus.com
mailing list for the glibc project.
Re: linux syslog problems (now linux-2.2.1+glibc-2.0.112)
- To: libc-hacker@gnu.org
- Subject: Re: linux syslog problems (now linux-2.2.1+glibc-2.0.112)
- From: smurf@noris.de (Matthias Urlichs)
- Date: 5 Feb 1999 16:02:46 +0100
- Newsgroups: dist.glibc
- Organization: noris network GmbH, Nuernberg, FRG
- References: <None> <199902022252.OAA12200@hircine.jk.ml.org> <918154551.24718@noris.de>
- Xref: noris.net dist.glibc:8049
John Kennedy <jk@csuchico.edu> writes:
>
> I don't know how it runs on other operating systems, but linux seems
> to prefer using a SOCK_STREAM (vs SOCK_DGRAM) PF_UNIX socket to talk
> to the syslog daemon (via /dev/log).
History lesson. Way back when (up to Linux 1.2 I believe), datagram sockets
for PF_UNIX weren't implemented, so syslogd had to use SOCK_STREAM (which
worked, since X needs them too ;-).
There are some patches floating around which fixup the Linux syslogd to use
SOCK_DGRAM sockets instead. IMHO that's the Right Thing to do before you
even think about finding other bugs. ;-) My version of such a patch is
appended below.
Glibc needs to talk to either version of syslogd, and it tries SOCK_DGRAM
first because, let's face it, that's the sensible way to do it.
> Damning symptoms were the clients locked up in syslog(), but still
> trying to send output (which didn't show up in the syslog file after
> the point where the socket was forgotten) up until the SOCK_STREAM
> buffer/backlog was filled, at which point it just blocked. At that point
Note that old syslogd used an integer for its FD_SET...
> I've yet to see a client get paranoid about a syslog() not returning
> promptly, probably because of the unreliable SOCK_DGRAM background.
That's the reason why libc5 supports SOCK_DGRAM for syslog (I got fed up
with the hangs and sent in patches to HJL).
> In any case, my daemons would normally be dead by now so I'm going
> to give them a full day before being calling it fixed.
Anyway, here's my patch to make syslog listen to the datagram socket
instead, like it's supposed to do. It's relative to version -24. Compile it
_without_ defining SYSLOG_STREAM.
Index: base.8/syslogd.c
--- base.8/syslogd.c Thu, 26 Feb 1998 05:40:49 +0100 smurf (kernel_sysklogd/1_syslogd.c 1.1.1.7 644)
+++ noris.8(w)/syslogd.c Fri, 13 Mar 1998 07:37:06 +0100 smurf (kernel_sysklogd/1_syslogd.c 1.1.1.11 664)
@@ -461,9 +461,12 @@
char *PidFile = _PATH_LOGPID;
char ctty[] = _PATH_CONSOLE;
+#ifdef SYSLOG_STREAM
char **parts;
+#endif
-int inetm = 0, funix = -1;
+int inetm = 0;
+int funix = -1;
static int debugging_on = 0;
static int nlogs = -1;
static int restart = 0;
@@ -631,10 +634,6 @@
int NoHops = 1; /* Can we bounce syslog messages through an
intermediate host. */
-extern int errno, sys_nerr;
-#if !defined(__GLIBC__)
-extern char *sys_errlist[];
-#endif /* __GLIBC__ */
extern char *ctime(), *index();
/* Function prototypes. */
@@ -686,7 +685,9 @@
#endif /* __GLIBC__ */
fd_set unixm, readfds;
+#ifdef SYSLOG_STREAM
int fd;
+#endif
#ifdef SYSLOG_UNIXAF
struct sockaddr_un fromunix;
#endif
@@ -849,6 +850,7 @@
/* Create a partial message table for all file descriptors. */
num_fds = getdtablesize();
+#ifdef SYSLOG_STREAM
dprintf("Allocated parts table for %d file descriptors.\n", num_fds);
if ( (parts = (char **) malloc(num_fds * sizeof(char *))) == \
(char **) 0 )
@@ -858,6 +860,7 @@
}
for(i= 0; i < num_fds; ++i)
parts[i] = (char *) 0;
+#endif
dprintf("Starting.\n");
init();
@@ -879,10 +882,12 @@
* descriptors.
*/
FD_SET(funix, &readfds);
+#ifdef SYSLOG_STREAM
for (nfds= 0; nfds < FD_SETSIZE; ++nfds)
if ( FD_ISSET(nfds, &unixm) )
FD_SET(nfds, &readfds);
#endif
+#endif
#ifdef SYSLOG_INET
/*
* Add the Internet Domain Socket to the list of read
@@ -932,7 +937,7 @@
dprintf(("\n"));
}
-#ifdef SYSLOG_UNIXAF
+#if defined(SYSLOG_UNIXAF) && defined(SYSLOG_STREAM)
if ( debugging_on )
{
dprintf("Checking UNIX connections, active: ");
@@ -950,7 +955,7 @@
printchopped(LocalHostName, line, i, fd);
} else if (i < 0) {
if (errno != EINTR) {
- logerror("recvfrom unix");
+ logerror("read from unix");
}
} else {
dprintf("Unix socket (%d) closed.\n", fd);
@@ -962,11 +967,11 @@
strlen(parts[fd]) + 1, \
fd);
}
- close(fd);
- FD_CLR(fd, &unixm);
- FD_CLR(fd, &readfds);
+ close(fd);
+ FD_CLR(fd, &unixm);
+ FD_CLR(fd, &readfds);
}
- }
+ }
/* Accept a new unix connection */
if (FD_ISSET(funix, &readfds)) {
len = sizeof(fromunix);
@@ -982,14 +987,33 @@
"%d = %s.\n", errno, strerror(errno));
}
}
-
#endif
+#if defined(SYSLOG_UNIXAF) && !defined(SYSLOG_STREAM)
+ if (FD_ISSET(funix, &readfds)) {
+ len = sizeof(fromunix);
+ memset(line, '\0', sizeof(line));
+ i = recvfrom(funix, line, MAXLINE - 2, 0, \
+ (struct sockaddr *) &fromunix, &len);
+ dprintf("Message from unix socket: #%d\n",
+ funix);
+ if (i > 0) {
+ line[i] = line[i+1] = '\0';
+ printchopped(LocalHostName, line, \
+ i + 2, funix);
+ } else if (i < 0 && errno != EINTR) {
+ dprintf("UNIX socket error: %d = %s.\n", \
+ errno, strerror(errno));
+ logerror("recvfrom unix");
+ sleep(10);
+ }
+ }
+#endif
#ifdef SYSLOG_INET
if (InetInuse && AcceptRemote && FD_ISSET(inetm, &readfds)) {
len = sizeof(frominet);
memset(line, '\0', sizeof(line));
- i = recvfrom(finet, line, MAXLINE - 2, 0, \
+ i = recvfrom(inetm, line, MAXLINE - 2, 0, \
(struct sockaddr *) &frominet, &len);
dprintf("Message from inetd socket: #%d, host: %s\n",
inetm, inet_ntoa(frominet.sin_addr));
@@ -1006,7 +1030,7 @@
* -Joey
*/
printchopped(from, line, \
- i + 2, finet);
+ i + 2, inetm);
} else if (i < 0 && errno != EINTR) {
dprintf("INET socket error: %d = %s.\n", \
errno, strerror(errno));
@@ -1034,10 +1058,20 @@
sunx.sun_family = AF_UNIX;
(void) strncpy(sunx.sun_path, LogName, sizeof(sunx.sun_path));
- fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ fd = socket(AF_UNIX,
+#ifdef SYSLOG_STREAM
+ SOCK_STREAM
+#else
+ SOCK_DGRAM
+#endif
+ , 0);
if (fd < 0 || bind(fd, (struct sockaddr *) &sunx,
sizeof(sunx.sun_family)+strlen(sunx.sun_path)) < 0 ||
- chmod(LogName, 0666) < 0 || listen(fd, 5) < 0) {
+ chmod(LogName, 0666) < 0
+#ifdef SYSLOG_STREAM
+ || listen(fd, 5) < 0
+#endif
+ ) {
(void) sprintf(line, "cannot create %s", LogName);
logerror(line);
dprintf("cannot create %s (%d).\n", LogName, errno);
@@ -1188,7 +1222,8 @@
dprintf("Message length: %d, File descriptor: %d.\n", len, fd);
tmpline[0] = '\0';
- if ( parts[fd] != (char *) 0 )
+#ifdef SYSLOG_STREAM
+ if ( fd >= 0 && parts[fd] != (char *) 0 )
{
dprintf("Including part from messages.\n");
strcpy(tmpline, parts[fd]);
@@ -1228,6 +1263,7 @@
memset(p, '\0', ptlngth);
}
}
+#endif
do {
end = strchr(start + 1, '\0');
@@ -1596,7 +1632,7 @@
l = strlen(line);
if (l > MAXLINE)
l = MAXLINE;
- if (sendto(finet, line, l, 0, \
+ if (sendto(inetm, line, l, 0, \
(struct sockaddr *) &f->f_un.f_forw.f_addr,
sizeof(f->f_un.f_forw.f_addr)) != l) {
int e = errno;
@@ -1932,12 +1968,7 @@
dprintf("Called logerr, msg: %s\n", type);
- if (errno == 0)
- (void) sprintf(buf, "syslogd: %s", type);
- else if ((unsigned) errno > sys_nerr)
- (void) sprintf(buf, "syslogd: %s: error %d", type, errno);
- else
- (void) sprintf(buf, "syslogd: %s: %s", type, sys_errlist[errno]);
+ (void) sprintf(buf, "syslogd: %s: %s", type, strerror(errno));
errno = 0;
logmsg(LOG_SYSLOG|LOG_ERR, buf, LocalHostName, ADDDATE);
return;
--
Matthias Urlichs | noris network GmbH | smurf@noris.de | ICQ: 20193661
The quote was selected randomly. Really. | http://www.noris.de/~smurf/
--
Love may make the world go round, but lust is the axis on which it
revolves