Making accept() not block
Aaron Hopkins
lists at die.net
Sun May 14 19:00:46 UTC 2006
Unpatched NSD 2.3.4 started with -N 2, strace attached to each child
process, then one query packet sent with dig:
The first child gets the query, sends the result, and goes back to select():
Process 11499 attached - interrupt to quit
select(5, [3 4], [], [], NULL) = 1 (in [3])
recvfrom(3, "j\331\1\0\0\1\0\0\0\0\0\0\3die\3net\0\0\1\0\1", 131337, 0, {sa_family=AF_INET, sin_port=htons(56031), sin_addr=inet_addr("209.151.236.4")}, [16]) = 25
sendto(3, "j\331\205\0\0\1\0\1\0\2\0\2\3die\3net\0\0\1\0\1\300\f\0"..., 109, 0, {sa_family=AF_INET, sin_port=htons(56031), sin_addr=inet_addr("209.151.236.4")}, 16) = 109
select(5, [3 4], [], [], NULL
The second child wakes up and blocks in recvfrom():
Process 11498 attached - interrupt to quit
select(5, [3 4], [], [], NULL) = 1 (in [3])
recvfrom(3,
If this were a socket that gets little or no real traffic, this child
becomes useless.
Same steps, but running NSD 2.3.4 patched to set O_NONBLOCK on the UDP
socket:
The first child acts the same:
Process 12722 attached - interrupt to quit
select(5, [3 4], [], [], NULL) = 1 (in [3])
recvfrom(3, "Dy\1\0\0\1\0\0\0\0\0\0\3die\3net\0\0\1\0\1", 131337, 0, {sa_family=AF_INET, sin_port=htons(56035), sin_addr=inet_addr("209.151.236.4")}, [16]) = 25sendto(3, "Dy\205\0\0\1\0\1\0\2\0\2\3die\3net\0\0\1\0\1\300\f\0\1"..., 109, 0, {sa_family=AF_INET, sin_port=htons(56035), sin_addr=inet_addr("209.151.236.4")}, 16) = 109
select(5, [3 4], [], [], NULL
The second wakes up, gets EAGAIN from recvfrom() and goes back to select():
Process 12723 attached - interrupt to quit
select(5, [3 4], [], [], NULL) = 1 (in [3])
recvfrom(3, 0xbf5df008, 131337, 0, 0x8c6a71c, 0x8c6a79c) = -1 EAGAIN (Resource temporarily unavailable)
select(5, [3 4], [], [], NULL
It still does unnecessary work here but at least it goes back to answering
other requests when it finds there is nothing to do.
-- Aaron
More information about the nsd-users
mailing list