Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 8 May 1999 16:22:36 +0200 (CEST)
From:      dan@obluda.cz
To:        FreeBSD-gnats-submit@freebsd.org
Subject:   bin/11594: INETD hangup problem report
Message-ID:  <199905081422.QAA10290@dan-h.fio.cz>

next in thread | raw e-mail | index | archive | help

>Number:         11594
>Category:       bin
>Synopsis:       hang problem in INETD
>Confidential:   no
>Severity:       serious
>Priority:       high
>Responsible:    freebsd-bugs
>State:          open
>Quarter:        
>Keywords:       
>Date-Required:
>Class:          sw-bug
>Submitter-Id:   current-users
>Arrival-Date:   Sat May  8 14:00:04 PDT 1999
>Closed-Date:
>Last-Modified:
>Originator:     Dan Lukes
>Release:        FreeBSD 3.1-RELEASE i386
>Organization:
Obludarium
>Environment:

	a system with inetd running

>Description:

	INETD hang if maximum number of child on all configured services 
        is reached
	Childs thats ends after it remain "zombie" forever.

        When the maximum child for a service is running, the service is
disabled (see last command of addchild() ). It remove the service's
socket descriptor from allsock (used in select() ) and do nsock-- (the
number of enabled services).

	After the last service is disabled by this mechanism, the nsock is
zero and allsock contain no descriptor but pipe descriptor for communicating
with signal handler functions.

	Lets inspect the neverending "for(;;)" in main():

           if (nsock == 0) {
                (void) sigblock(SIGBLOCK);
                while (nsock == 0)
                    sigpause(0L);
                (void) sigsetmask(0L);
            }

	Entering the while() is the last action in program's life as no signal
handler never change the nsock variable directly, so while never end. Signal 
handlers writes the "I'm has been invoked!" mark in pipe only. The code
processing those marks on the other end of pipe is never invoked. This is
true for SIGCHLD also, so wait() is never called and childs remain in
"zombie" status until inetd exit.

>How-To-Repeat:

	Create inetd.conf with one "wait" service only.
	Run (restart) inetd.
	Connect to service.

	The inetd is in neverending loop now until terminated.
>Fix:

	I see no reason for existence problematic code in source code. The
allsock variable ever contain at least the read end of pipe descriptor, so the 
list of socket is never empty. 
	Well, it's not so good to wait in select() for output from signal 
handler routines as the select() will terminate with errno=EINTR when signal
arrive, but "continue" immediately wrap execution back to new select(). It
immediately detect the pipe's end is ready for reading (if EINTR has been 
caused by one of "our" signal). I thing the one system call overhead can be 
ignored. 
	The suggested fix:

*** inetd.c.ORIG        Tue Jan  5 12:56:35 1999
--- inetd.c     Sat May  8 13:19:20 1999
***************
*** 447,458 ****
            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) {
--- 447,452 ----


	Note, I look to old FreeBSD's sources and it's very old error. 
        IMHO, it may come from original Berkeley sources and may appear
in other systems derived from those sources too.

	This problem report MAY fix the problem report i386/10468




>Release-Note:
>Audit-Trail:
>Unformatted:


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




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