Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 8 Jan 1999 07:42:23 +0200 (SAT)
From:      Peter van Heusden <pvh@leftside.wcape.school.za>
To:        freebsd-stable@FreeBSD.ORG
Subject:   Patch for inetd.c in realloc() problem
Message-ID:  <Pine.BSF.4.02A.9901080724200.14499-100000@leftside.wcape.school.za>

next in thread | raw e-mail | index | archive | help
I have made a version of Graham Wheeler's inetd patch which fixes signal
handling in inetd. This prevents the 'inetd in realloc(): warning: junk
pointer, too low to make sense'.

The patch is basically a slightly modified version of the same patch
applied to -CURRENT.

Unfortunately, however, I don't use inetd particularly heavily. I would
appreciate it if someone who does use inetd heavily could apply the patch
and check that there are no adverse effects.

Here's the patch - it must be applied to the latest version of inetd.c
(rev 1.15.2.11):

Peter

--- inetd.c-REALSTABLE	Thu Jan  7 08:25:11 1999
+++ inetd.c	Thu Jan  7 08:49:23 1999
@@ -42,7 +42,7 @@
 static char sccsid[] = "@(#)from: inetd.c	8.4 (Berkeley) 4/13/94";
 #endif
 static const char rcsid[] =
-	"$Id: inetd.c,v 1.15.2.11 1998/12/16 00:00:12 dillon Exp $";
+	"$Id: inetd.c,v 1.15.2.12 1998/12/16 00:00:12 dillon Exp $";
 #endif /* not lint */
 
 /*
@@ -172,6 +172,7 @@
 struct	servent *sp;
 struct	rpcent *rpc;
 struct	in_addr bind_address;
+int	signalpipe[2];
 
 struct	servtab {
 	char	*se_service;		/* name of service */
@@ -217,7 +218,9 @@
 void		chargen_dg __P((int, struct servtab *));
 void		chargen_stream __P((int, struct servtab *));
 void		close_sep __P((struct servtab *));
-void		config __P((int));
+void		flag_signal __P((char));
+void		flag_config __P((int));
+void		config __P((void));
 void		daytime_dg __P((int, struct servtab *));
 void		daytime_stream __P((int, struct servtab *));
 void		discard_dg __P((int, struct servtab *));
@@ -234,10 +237,12 @@
 char	       *nextline __P((FILE *));
 void		print_service __P((char *, struct servtab *));
 void		addchild __P((struct servtab *, int));
-void		reapchild __P((int));
+void		flag_reapchild __P((int));
+void		reapchild __P((void));
 void		enable __P((struct servtab *));
 void		disable __P((struct servtab *));
-void		retry __P((int));
+void		flag_retry __P((int));
+void		retry __P((void));
 int		setconfig __P((void));
 void		setup __P((struct servtab *));
 char	       *sskip __P((char **));
@@ -408,12 +413,12 @@
 	sigaddset(&sa.sa_mask, SIGALRM);
 	sigaddset(&sa.sa_mask, SIGCHLD);
 	sigaddset(&sa.sa_mask, SIGHUP);
-	sa.sa_handler = retry;
+	sa.sa_handler = flag_retry;
 	sigaction(SIGALRM, &sa, (struct sigaction *)0);
-	config(SIGHUP);
-	sa.sa_handler = config;
+	config();
+	sa.sa_handler = flag_config;
 	sigaction(SIGHUP, &sa, (struct sigaction *)0);
-	sa.sa_handler = reapchild;
+	sa.sa_handler = flag_reapchild;
 	sigaction(SIGCHLD, &sa, (struct sigaction *)0);
 	sa.sa_handler = SIG_IGN;
 	sigaction(SIGPIPE, &sa, &sapipe);
@@ -428,47 +433,69 @@
 		(void)setenv("inetd_dummy", dummy, 1);
 	}
 
-	(void) sigblock(SIGBLOCK);
+	if (pipe(signalpipe) != 0)
+	{
+	    syslog(LOG_ERR, "pipe: %%m");
+	    exit(EX_OSERR);
+	}
+	FD_SET(signalpipe[0], &allsock);
+	if (signalpipe[0]>maxsock) maxsock = signalpipe[0];
 
 	for (;;) {
 	    int n, ctrl;
 	    fd_set readable;
-	    struct timeval tv = { 5, 0 };
-
-	    /*
-	     * Handle signal masking and select.  Signals are unmasked and
-	     * we pause if we have no active descriptors.  If we do have 
-	     * active descriptors, leave signals unmasked through the select()
-	     * call.  The select() call is inclusive of a timeout in order
-	     * to handle the race condition where a signal occurs just prior
-	     * to the select() call and potentially changes the allsock
-	     * fd_set, to prevent select() from potentially blocking forever.
-	     *
-	     * Signals are masked at all other times.
-	     */
 
 
 	    if (nsock == 0) {
+		(void) sigblock(SIGBLOCK);
 		while (nsock == 0)
 		    sigpause(0L);
+		(void) sigsetmask(0L);
 	    }
-
-	    (void) sigsetmask(0L);
-
-
 	    readable = allsock;
-	    errno = 0;
-	    n = select(maxsock + 1, &readable, NULL, NULL, &tv);
-
-	    (void) sigblock(SIGBLOCK);
-
-	    if (n <= 0) {
-		    if (n < 0 && errno && errno != EINTR) {
+	    if ((n = select(maxsock + 1, &readable, (fd_set *)0,
+		(fd_set *)0, (struct timeval *)0)) <= 0) {
+		    if (n < 0 && errno != EINTR) {
 			syslog(LOG_WARNING, "select: %m");
 			sleep(1);
 		    }
 		    continue;
 	    }
+	    /* handle any queued signal flags */
+	    if (FD_ISSET(signalpipe[0], &readable))
+	    {
+		int n;
+		if (ioctl(signalpipe[0], FIONREAD, &n) == 0)
+		{
+		    while (--n >= 0)
+		    {
+			char c;
+			if (read(signalpipe[0], &c, 1) == 1)
+			{
+			    if (debug) warnx("Handling signal flag %c", c);
+		    	    switch(c)
+		    	    {
+		    	    case 'A': /* sigalrm */
+				retry(); break;
+		    	    case 'C': /* sigchld */
+				reapchild(); break;
+		    	    case 'H': /* sighup */
+				config(); break;
+		    	    }
+			}
+			else
+			{
+		    	    syslog(LOG_ERR, "read: %m");
+		    	    exit(EX_OSERR);
+			}
+		    }
+		}
+		else
+		{
+		    syslog(LOG_ERR, "ioctl: %m");
+		    exit(EX_OSERR);
+		}
+	    }
 	    for (sep = servtab; n && sep; sep = sep->se_next)
 	        if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
 		    n--;
@@ -506,7 +533,7 @@
 			    }
 		    } else
 			    ctrl = sep->se_fd;
-		    /* (void) sigblock(SIGBLOCK); */
+		    (void) sigblock(SIGBLOCK);
 		    pid = 0;
 		    dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
 		    if (dofork) {
@@ -527,7 +554,7 @@
 			"%s/%s server failing (looping), service terminated",
 					    sep->se_service, sep->se_proto);
 					close_sep(sep);
-					/* sigsetmask(0L); */
+					sigsetmask(0L);
 					if (!timingout) {
 						timingout = 1;
 						alarm(RETRYTIME);
@@ -542,13 +569,13 @@
 			    if (sep->se_accept &&
 				sep->se_socktype == SOCK_STREAM)
 				    close(ctrl);
-			    /* sigsetmask(0L); */
+			    sigsetmask(0L);
 			    sleep(1);
 			    continue;
 		    }
 		    if (pid)
 			addchild(sep, pid);
-		    /* sigsetmask(0L); */
+		    sigsetmask(0L);
 		    if (pid == 0) {
 			    if (dofork) {
 				if (debug)
@@ -654,7 +681,6 @@
 #endif
 				sigaction(SIGPIPE, &sapipe,
 				    (struct sigaction *)0);
-				(void) sigsetmask(0L);
 				execv(sep->se_server, sep->se_argv);
 				if (sep->se_socktype != SOCK_STREAM)
 					recv(0, buf, sizeof (buf), 0);
@@ -670,6 +696,20 @@
 }
 
 /*
+ * Add a signal flag to the signal flag queue for later handling
+ */
+
+void flag_signal(c)
+    char c;
+{
+    if (write(signalpipe[1], &c, 1) != 1)
+    {
+	syslog(LOG_ERR, "write: %m");
+	exit(EX_OSERR);
+    }
+}
+
+/*
  * Record a new child pid for this service. If we've reached the
  * limit on children, then stop accepting incoming requests.
  */
@@ -696,9 +736,15 @@
  */
 
 void
-reapchild(signo)
+flag_reapchild(signo)
 	int signo;
 {
+    flag_signal('C');
+}
+
+void
+reapchild()
+{
 	int k, status;
 	pid_t pid;
 	struct servtab *sep;
@@ -728,11 +774,16 @@
 }
 
 void
-config(signo)
+flag_config(signo)
 	int signo;
 {
+    flag_signal('H');
+}
+
+void config()
+{
 	struct servtab *sep, *new, **sepp;
-	/* long omask; */
+	long omask;
 
 	if (!setconfig()) {
 		syslog(LOG_ERR, "%s: %m", CONFIG);
@@ -770,7 +821,7 @@
 			int i;
 
 #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
-			/* omask = sigblock(SIGBLOCK); */
+			omask = sigblock(SIGBLOCK);
 			/* copy over outstanding child pids */
 			if (sep->se_maxchild && new->se_maxchild) {
 				new->se_numchild = sep->se_numchild;
@@ -803,7 +854,7 @@
 			SWAP(sep->se_server, new->se_server);
 			for (i = 0; i < MAXARGV; i++)
 				SWAP(sep->se_argv[i], new->se_argv[i]);
-			/* sigsetmask(omask); */
+			sigsetmask(omask);
 			freeconfig(new);
 			if (debug)
 				print_service("REDO", sep);
@@ -858,7 +909,7 @@
 	/*
 	 * Purge anything not looked at above.
 	 */
-	/* omask = sigblock(SIGBLOCK); */
+	omask = sigblock(SIGBLOCK);
 	sepp = &servtab;
 	while ((sep = *sepp)) {
 		if (sep->se_checked) {
@@ -875,7 +926,7 @@
 		freeconfig(sep);
 		free((char *)sep);
 	}
-	/* (void) sigsetmask(omask); */
+	(void) sigsetmask(omask);
 }
 
 void
@@ -884,9 +935,9 @@
 {
         int i;
         struct servtab *sepp;
-	/* long omask; */
+	long omask;
 
-	/* omask = sigblock(SIGBLOCK); */
+	omask = sigblock(SIGBLOCK);
         for (sepp = servtab; sepp; sepp = sepp->se_next) {
                 if (sepp == sep)
                         continue;
@@ -903,13 +954,19 @@
         if (sep->se_fd != -1)
                 (void) close(sep->se_fd);
         sep->se_fd = -1;
-	/* (void) sigsetmask(omask); */
+	(void) sigsetmask(omask);
 }
 
 void
-retry(signo)
+flag_retry(signo)
 	int signo;
 {
+    flag_signal('A');
+}
+
+void
+retry()
+{
 	struct servtab *sep;
 
 	timingout = 0;
@@ -1016,7 +1073,7 @@
 	struct servtab *cp;
 {
 	struct servtab *sep;
-	/* long omask; */
+	long omask;
 
 	sep = (struct servtab *)malloc(sizeof (*sep));
 	if (sep == (struct servtab *)0) {
@@ -1025,10 +1082,10 @@
 	}
 	*sep = *cp;
 	sep->se_fd = -1;
-	/* omask = sigblock(SIGBLOCK); */
+	omask = sigblock(SIGBLOCK);
 	sep->se_next = servtab;
 	servtab = sep;
-	/* sigsetmask(omask); */
+	sigsetmask(omask);
 	return (sep);
 }
 
@@ -1775,9 +1832,6 @@
 /*
  *  Based on TCPMUX.C by Mark K. Lottor November 1988
  *  sri-nic::ps:<mkl>tcpmux.c
- *
- *  signals are masked on call, we have to unmask SIGALRM for the
- *  duration of the read
  */
 
 
@@ -1788,38 +1842,27 @@
 	int len;
 {
 	int count = 0, n;
-	int not_done = 1;
 	struct sigaction sa;
-	long omask;
 
 	sa.sa_flags = 0;
 	sigemptyset(&sa.sa_mask);
 	sa.sa_handler = SIG_DFL;
 	sigaction(SIGALRM, &sa, (struct sigaction *)0);
-
-	omask = sigsetmask(SIGBLOCK & ~sigmask(SIGALRM));
-
 	do {
 		alarm(10);
 		n = read(fd, buf, len-count);
 		alarm(0);
 		if (n == 0)
-			break;
-		if (n < 0) {
-			count = -1;
-			break;
-		}
+			return (count);
+		if (n < 0)
+			return (-1);
 		while (--n >= 0) {
-			if (*buf == '\r' || *buf == '\n' || *buf == '\0') {
-				not_done = 0;
-				break;
-			}
+			if (*buf == '\r' || *buf == '\n' || *buf == '\0')
+				return (count);
 			count++;
 			buf++;
 		}
-	} while (not_done && count < len);
-
-	sigsetmask(omask);
+	} while (count < len);
 	return (count);
 }
 

--
Peter van Heusden |    Its the 90's, and collective action is STILL cool!
pvh@leftside.wcape.school.za | Get active in your union today!


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-stable" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?Pine.BSF.4.02A.9901080724200.14499-100000>