This is the mail archive of the libc-hacker@cygnus.com mailing list for the glibc project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: linux syslog problems (now linux-2.2.1+glibc-2.0.112)


  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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]