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>