Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 10 Dec 1998 23:22:26 -0800 (PST)
From:      Matthew Dillon <dillon@apollo.backplane.com>
To:        Warner Losh <imp@village.org>
Cc:        Archie Cobbs <archie@whistle.com>, jwd@unx.sas.com, freebsd-current@FreeBSD.ORG
Subject:   inetd commit candidate (was Re: inetd: realloc/free bug )
Message-ID:  <199812110722.XAA35442@apollo.backplane.com>

next in thread | raw e-mail | index | archive | help
    (diff relative to current cvs version)

    I've done some testing of this patch on one of our more heavily loaded
    shell machines and it seems to hold up, so it is now a commit candidate.

    However, since I do not get the realloc/free errors it would be good if
    some of the people who do test this patch on their own systems.

					    -Matt

    Matthew Dillon  Engineering, HiWay Technologies, Inc. & BEST Internet 
                    Communications & God knows what else.
    <dillon@backplane.com> (Please include original email in any response)    

Index: inetd.c
===================================================================
RCS file: /home/ncvs/src/usr.sbin/inetd/inetd.c,v
retrieving revision 1.41
diff -c -r1.41 inetd.c
*** inetd.c	1998/11/04 19:39:46	1.41
--- inetd.c	1998/12/11 07:19:18
***************
*** 431,450 ****
  		(void)setenv("inetd_dummy", dummy, 1);
  	}
  
  	for (;;) {
  	    int n, ctrl;
  	    fd_set readable;
  
  	    if (nsock == 0) {
- 		(void) sigblock(SIGBLOCK);
  		while (nsock == 0)
  		    sigpause(0L);
- 		(void) sigsetmask(0L);
  	    }
  	    readable = allsock;
! 	    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);
  		    }
--- 431,472 ----
  		(void)setenv("inetd_dummy", dummy, 1);
  	}
  
+ 	(void) sigblock(SIGBLOCK);
+ 
  	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) {
  		while (nsock == 0)
  		    sigpause(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) {
  			syslog(LOG_WARNING, "select: %m");
  			sleep(1);
  		    }
***************
*** 490,496 ****
  			    }
  		    } else
  			    ctrl = sep->se_fd;
! 		    (void) sigblock(SIGBLOCK);
  		    pid = 0;
  		    dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
  		    if (dofork) {
--- 512,518 ----
  			    }
  		    } else
  			    ctrl = sep->se_fd;
! 		    /* (void) sigblock(SIGBLOCK); */
  		    pid = 0;
  		    dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
  		    if (dofork) {
***************
*** 509,515 ****
  			"%s/%s server failing (looping), service terminated",
  					    sep->se_service, sep->se_proto);
  					close_sep(sep);
! 					sigsetmask(0L);
  					if (!timingout) {
  						timingout = 1;
  						alarm(RETRYTIME);
--- 531,537 ----
  			"%s/%s server failing (looping), service terminated",
  					    sep->se_service, sep->se_proto);
  					close_sep(sep);
! 					/* sigsetmask(0L); */
  					if (!timingout) {
  						timingout = 1;
  						alarm(RETRYTIME);
***************
*** 524,536 ****
  			    if (sep->se_accept &&
  				sep->se_socktype == SOCK_STREAM)
  				    close(ctrl);
! 			    sigsetmask(0L);
  			    sleep(1);
  			    continue;
  		    }
  		    if (pid)
  			addchild(sep, pid);
! 		    sigsetmask(0L);
  		    if (pid == 0) {
  			    if (dofork) {
  				if (debug)
--- 546,558 ----
  			    if (sep->se_accept &&
  				sep->se_socktype == SOCK_STREAM)
  				    close(ctrl);
! 			    /* sigsetmask(0L); */
  			    sleep(1);
  			    continue;
  		    }
  		    if (pid)
  			addchild(sep, pid);
! 		    /* sigsetmask(0L); */
  		    if (pid == 0) {
  			    if (dofork) {
  				if (debug)
***************
*** 713,719 ****
  	int signo;
  {
  	struct servtab *sep, *new, **sepp;
! 	long omask;
  
  	if (!setconfig()) {
  		syslog(LOG_ERR, "%s: %m", CONFIG);
--- 735,741 ----
  	int signo;
  {
  	struct servtab *sep, *new, **sepp;
! 	/* long omask; */
  
  	if (!setconfig()) {
  		syslog(LOG_ERR, "%s: %m", CONFIG);
***************
*** 751,757 ****
  			int i;
  
  #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
! 			omask = sigblock(SIGBLOCK);
  			/* copy over outstanding child pids */
  			if (sep->se_maxchild && new->se_maxchild) {
  				new->se_numchild = sep->se_numchild;
--- 773,779 ----
  			int i;
  
  #define SWAP(a, b) { typeof(a) c = a; a = b; b = c; }
! 			/* omask = sigblock(SIGBLOCK); */
  			/* copy over outstanding child pids */
  			if (sep->se_maxchild && new->se_maxchild) {
  				new->se_numchild = sep->se_numchild;
***************
*** 784,790 ****
  			SWAP(sep->se_server, new->se_server);
  			for (i = 0; i < MAXARGV; i++)
  				SWAP(sep->se_argv[i], new->se_argv[i]);
! 			sigsetmask(omask);
  			freeconfig(new);
  			if (debug)
  				print_service("REDO", sep);
--- 806,812 ----
  			SWAP(sep->se_server, new->se_server);
  			for (i = 0; i < MAXARGV; i++)
  				SWAP(sep->se_argv[i], new->se_argv[i]);
! 			/* sigsetmask(omask); */
  			freeconfig(new);
  			if (debug)
  				print_service("REDO", sep);
***************
*** 839,845 ****
  	/*
  	 * Purge anything not looked at above.
  	 */
! 	omask = sigblock(SIGBLOCK);
  	sepp = &servtab;
  	while ((sep = *sepp)) {
  		if (sep->se_checked) {
--- 861,867 ----
  	/*
  	 * Purge anything not looked at above.
  	 */
! 	/* omask = sigblock(SIGBLOCK); */
  	sepp = &servtab;
  	while ((sep = *sepp)) {
  		if (sep->se_checked) {
***************
*** 856,862 ****
  		freeconfig(sep);
  		free((char *)sep);
  	}
! 	(void) sigsetmask(omask);
  }
  
  void
--- 878,884 ----
  		freeconfig(sep);
  		free((char *)sep);
  	}
! 	/* (void) sigsetmask(omask); */
  }
  
  void
***************
*** 865,873 ****
  {
          int i;
          struct servtab *sepp;
! 	long omask;
  
! 	omask = sigblock(SIGBLOCK);
          for (sepp = servtab; sepp; sepp = sepp->se_next) {
                  if (sepp == sep)
                          continue;
--- 887,895 ----
  {
          int i;
          struct servtab *sepp;
! 	/* long omask; */
  
! 	/* omask = sigblock(SIGBLOCK); */
          for (sepp = servtab; sepp; sepp = sepp->se_next) {
                  if (sepp == sep)
                          continue;
***************
*** 884,890 ****
          if (sep->se_fd != -1)
                  (void) close(sep->se_fd);
          sep->se_fd = -1;
! 	(void) sigsetmask(omask);
  }
  
  void
--- 906,912 ----
          if (sep->se_fd != -1)
                  (void) close(sep->se_fd);
          sep->se_fd = -1;
! 	/* (void) sigsetmask(omask); */
  }
  
  void
***************
*** 997,1003 ****
  	struct servtab *cp;
  {
  	struct servtab *sep;
! 	long omask;
  
  	sep = (struct servtab *)malloc(sizeof (*sep));
  	if (sep == (struct servtab *)0) {
--- 1019,1025 ----
  	struct servtab *cp;
  {
  	struct servtab *sep;
! 	/* long omask; */
  
  	sep = (struct servtab *)malloc(sizeof (*sep));
  	if (sep == (struct servtab *)0) {
***************
*** 1006,1015 ****
  	}
  	*sep = *cp;
  	sep->se_fd = -1;
! 	omask = sigblock(SIGBLOCK);
  	sep->se_next = servtab;
  	servtab = sep;
! 	sigsetmask(omask);
  	return (sep);
  }
  
--- 1028,1037 ----
  	}
  	*sep = *cp;
  	sep->se_fd = -1;
! 	/* omask = sigblock(SIGBLOCK); */
  	sep->se_next = servtab;
  	servtab = sep;
! 	/* sigsetmask(omask); */
  	return (sep);
  }
  
***************
*** 1783,1788 ****
--- 1805,1813 ----
  /*
   *  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.
   */
  
  
***************
*** 1794,1812 ****
  {
  	int count = 0, n;
  	struct sigaction sa;
  
  	sa.sa_flags = 0;
  	sigemptyset(&sa.sa_mask);
  	sa.sa_handler = SIG_DFL;
  	sigaction(SIGALRM, &sa, (struct sigaction *)0);
  	do {
  		alarm(10);
  		n = read(fd, buf, len-count);
  		alarm(0);
  		if (n == 0)
! 			return (count);
! 		if (n < 0)
! 			return (-1);
  		while (--n >= 0) {
  			if (*buf == '\r' || *buf == '\n' || *buf == '\0')
  				return (count);
--- 1819,1843 ----
  {
  	int count = 0, n;
  	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;
! 		}
  		while (--n >= 0) {
  			if (*buf == '\r' || *buf == '\n' || *buf == '\0')
  				return (count);
***************
*** 1814,1819 ****
--- 1845,1852 ----
  			buf++;
  		}
  	} while (count < len);
+ 
+ 	sigsetmask(omask);
  	return (count);
  }
  

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



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?199812110722.XAA35442>