Making accept() not block

Aaron Hopkins lists at die.net
Fri May 12 11:02:23 UTC 2006


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));




More information about the nsd-users mailing list