NSD currently assumes that selecting on a TCP listen() socket will always
result in accept() not blocking. However, it doesn't mark its TCP listen()
sockets as non-blocking, so there is probably a race condition at least on
some OSes with either the -N flag (number of servers to fork) set to 2 or
more, or if someone opens a connection and closes it by the time NSD tries
to accept(). This may result in NSD not answering any requests until it
receives its next TCP connection.
There is a simple fix to this, which is to just mark the listen() socket as
non-blocking. An example patch against NSD 2.3.4 is attached below. Or you
may download it from:
https://www.die.net/tmp/5301574a642cbb78/nsd-2.3.4-nonblockingaccept.patch
-- Aaron
---
diff -ur nsd-2.3.4/server.c nsd-2.3.4.safer/server.c
--- nsd-2.3.4/server.c 2006-04-06 07:26:35.000000000 -0700
+++ nsd-2.3.4.safer/server.c 2006-05-12 03:44:50.000000000 -0700
@@ -308,6 +308,11 @@
}
#endif
+ if (fcntl(nsd->tcp[i].s, F_SETFL, O_NONBLOCK) == -1) {
+ log_msg(LOG_ERR, "fcntl failed: %s", strerror(errno));
+ return -1;
+ }
+
/* Bind it... */
if (bind(nsd->tcp[i].s, (struct sockaddr *)
nsd->tcp[i].addr->ai_addr, nsd->tcp[i].addr->ai_addrlen) != 0) {
log_msg(LOG_ERR, "can't bind the socket: %s",
strerror(errno));