Subject: bin/30253: Race condition in identd -b (pipe: no child processes)
To: None <gnats-admin@netbsd.org, netbsd-bugs@netbsd.org>
From: None <pmcphee@dilbert.givex.com>
List: netbsd-bugs
Date: 05/17/2005 13:31:00
>Number: 30253
>Category: bin
>Synopsis: Race condition in identd -b (pipe: no child processes)
>Confidential: no
>Severity: serious
>Priority: medium
>Responsible: bin-bug-people
>State: open
>Class: sw-bug
>Submitter-Id: net
>Arrival-Date: Tue May 17 13:31:00 +0000 2005
>Originator: Patrick McPhee
>Release: NetBSD 2.0_RC4
>Organization:
Givex Canada Corporation
>Environment:
System: NetBSD dilbert 2.0_RC4 NetBSD 2.0_RC4 (GIVEX) #0: Sat Oct 9 04:10:28 EDT 2004 door@dilbert:/usr/src/sys/arch/i386/compile/GIVEX i386
Architecture: i386
Machine: i386
>Description:
When run as a daemon, identd sometimes fails with the error
"poll: No child processes"
The problem arises when two or more identd requests are handled at roughly
the same time. If poll is interrupted by SIGCLD from one child process,
it returns -1 and sets errno to EINTR. If a second child process returns
between the time poll() sets errno and identd tests errno, the signal
handler sets errno to ECHILD. identd treats this as a fatal error.
>How-To-Repeat:
Flood identd with concurrent requests.
>Fix:
This patch fixes the problem. openbsd has fixed this by moving the call
to waitpid() out of the signal handler.
A work-around is to run identd -b in a wrapper which waits for it to
exit and restarts it.
Index: identd.c
===================================================================
RCS file: /cvsroot/src/libexec/identd/identd.c,v
retrieving revision 1.22.2.1
diff -u -r1.22.2.1 identd.c
--- identd.c 18 Sep 2004 19:14:41 -0000 1.22.2.1
+++ identd.c 7 Apr 2005 13:26:02 -0000
@@ -221,7 +221,7 @@
/* Mainloop for daemon */
for (;;) {
rv = poll(rfds, nfds, INFTIM);
- if (rv < 0 && errno == EINTR)
+ if (rv < 0 && (errno == EINTR || errno == ECHILD))
continue;
if (rv < 0)
fatal("poll");