Article 1 of news.software.nntp:
Path: news.pop.psu.edu!news.cac.psu.edu!howland.reston.ans.net!europa.eng.gtefsd.com!uunet!charon.citicorp.com!charon.citicorp.com!not-for-mail
From: philip@charon.citicorp.com (Philip Gladstone)
Newsgroups: news.software.nntp
Subject: Re: inn chews up CPU
Date: 31 Aug 1993 17:59:39 -0400
Organization: Citicorp
Lines: 182
Distribution: inet
Message-ID: <260hkb$5t5@charon.citicorp.com>
References: <25ts5l$3dej@thebes.cc.waikato.ac.nz> <25vgslINNb43@rodan.UU.NET>
Reply-To: Philip.Gladstone@mail.citicorp.com
NNTP-Posting-Host: charon.citicorp.com
X-Newsreader: TIN [version 1.2 PL1]

Rich Salz (rsalz@rodan.UU.NET) wrote:
: There is  a bug in INN1.4. Under some circumstances innd can lose track
: of a file descriptor and end up sitting in a select() loop.  I'm in the
: middle of 1.5 work right now, and I don't have the fix available.
: Perhaps someone can post it?  Thanks.
: 	/r$

This is the patch that worked for me:


*** 1.30	1993/03/18 21:04:22
--- innd/chan.c	1993/07/23 14:53:31
***************
*** 759,772 ****
  	startpoint = fd;
  	do {
  	    cp = &CHANtable[fd];
- 	    if (cp->Type == CTfree)
- 		goto Next;
  
  	    /* Anything to read? */
  	    if (FD_ISSET(fd, &RCHANmask) && FD_ISSET(fd, &MyRead)) {
  		count--;
! 		cp->LastActive = Now.time;
! 		(*cp->Reader)(cp);
  	    }
  
  	    /* Possibly recheck for dead children so we don't get SIGPIPE
--- 787,807 ----
  	startpoint = fd;
  	do {
  	    cp = &CHANtable[fd];
  
  	    /* Anything to read? */
  	    if (FD_ISSET(fd, &RCHANmask) && FD_ISSET(fd, &MyRead)) {
  		count--;
! 		if (cp->Type == CTfree) {
! 		    syslog(L_ERROR, "%s %d free but was in RMASK",
! 			CHANname(cp), fd);
! 		    /* Don't call RCHANremove since cp->fd will be -1. */
! 		    FD_CLR(fd, &RCHANmask);
! 		    (void)close(fd);
! 		}
! 		else {
! 		    cp->LastActive = Now.time;
! 		    (*cp->Reader)(cp);
! 		}
  	    }
  
  	    /* Possibly recheck for dead children so we don't get SIGPIPE
***************
*** 777,828 ****
  	    /* Ready to write? */
  	    if (FD_ISSET(fd, &WCHANmask) && FD_ISSET(fd, &MyWrite)) {
  		count--;
! 		bp = &cp->Out;
! 		if (bp->Left) {
! 		    cp->LastActive = Now.time;
! 		    i = largewrite(fd, &bp->Data[bp->Used], bp->Left);
! 		    if (i <= 0) {
! 			oerrno = errno;
! 			p = CHANname(cp);
! 			errno = oerrno;
! 			if (i < 0)
! 			    syslog(L_ERROR, "%s cant write %m", p);
! 			else
! 			    syslog(L_ERROR, "%s cant write", p);
! 			cp->BadWrites++;
! 			if (i < 0 && oerrno == EPIPE) {
! 			    SITEchanclose(cp);
! 			    CHANclose(cp, p);
! 			}
! 			else if (i < 0 && oerrno == EWOULDBLOCK) {
! 			    WCHANremove(cp);
! 			    CHANwritesleep(cp, p);
! 			}
! 			else if (cp->BadWrites >= BAD_IO_COUNT) {
! 			    syslog(L_ERROR, "%s sleeping", p);
! 			    WCHANremove(cp);
! 			    SCHANadd(cp, (time_t)(Now.time + PAUSE_RETRY_TIME),
! 				(POINTER)NULL, CHANwakeup, (POINTER)NULL);
  			}
! 		    }
! 		    else {
! 			cp->BadWrites = 0;
! 			cp->BlockedWrites = 0;
! 			bp->Left -= i;
! 			bp->Used += i;
! 			if (bp->Left <= 0) {
! 			    WCHANremove(cp);
! 			    (*cp->WriteDone)(cp);
  			}
  		    }
  		}
  	    }
  
  	    /* Coming off a sleep? */
  	    if (FD_ISSET(fd, &SCHANmask) && cp->Waketime <= Now.time) {
! 		cp->LastActive = Now.time;
! 		SCHANremove(cp);
! 		(*cp->Waker)(cp);
  	    }
  
  	    /* Has this channel been inactive very long? */
--- 812,882 ----
  	    /* Ready to write? */
  	    if (FD_ISSET(fd, &WCHANmask) && FD_ISSET(fd, &MyWrite)) {
  		count--;
! 		if (cp->Type == CTfree) {
! 		    syslog(L_ERROR, "%s %d free but was in WMASK",
! 			CHANname(cp), fd);
! 		    /* Don't call WCHANremove since cp->fd will be -1. */
! 		    FD_CLR(fd, &WCHANmask);
! 		    (void)close(fd);
! 		}
! 		else {
! 		    bp = &cp->Out;
! 		    if (bp->Left) {
! 			cp->LastActive = Now.time;
! 			i = largewrite(fd, &bp->Data[bp->Used], bp->Left);
! 			if (i <= 0) {
! 			    oerrno = errno;
! 			    p = CHANname(cp);
! 			    errno = oerrno;
! 			    if (i < 0)
! 				syslog(L_ERROR, "%s cant write %m", p);
! 			    else
! 				syslog(L_ERROR, "%s cant write", p);
! 			    cp->BadWrites++;
! 			    if (i < 0 && oerrno == EPIPE) {
! 				SITEchanclose(cp);
! 				CHANclose(cp, p);
! 			    }
! 			    else if (i < 0 && oerrno == EWOULDBLOCK) {
! 				WCHANremove(cp);
! 				CHANwritesleep(cp, p);
! 			    }
! 			    else if (cp->BadWrites >= BAD_IO_COUNT) {
! 				syslog(L_ERROR, "%s sleeping", p);
! 				WCHANremove(cp);
! 				SCHANadd(cp,
! 				    (time_t)(Now.time + PAUSE_RETRY_TIME),
! 				    (POINTER)NULL, CHANwakeup, (POINTER)NULL);
! 			    }
  			}
! 			else {
! 			    cp->BadWrites = 0;
! 			    cp->BlockedWrites = 0;
! 			    bp->Left -= i;
! 			    bp->Used += i;
! 			    if (bp->Left <= 0) {
! 				WCHANremove(cp);
! 				(*cp->WriteDone)(cp);
! 			    }
  			}
  		    }
+ 		    else
+ 			/* Should not be possible. */
+ 			WCHANremove(cp);
  		}
  	    }
  
  	    /* Coming off a sleep? */
  	    if (FD_ISSET(fd, &SCHANmask) && cp->Waketime <= Now.time) {
! 		if (cp->Type == CTfree) {
! 		    syslog(L_ERROR,"%s ERROR s-select free %d",CHANname(cp),fd);
! 		    FD_CLR(fd, &SCHANmask);
! 		    (void) close(fd);
! 		} else {
! 		    cp->LastActive = Now.time;
! 		    SCHANremove(cp);
! 		    (*cp->Waker)(cp);
! 		}
  	    }
  
  	    /* Has this channel been inactive very long? */


-- 
Philip Gladstone - Consultant
Citicorp Global Information Network
I don't speak for Citicorp. I presume that somebody else does!


