Writing

Software, technology, sysadmin war stories, and more. Feed
Tuesday, October 11, 2011

FD_ZERO your fd_sets or suffer

Have you ever run into this problem before? You have a select loop. It's the same old same old: keep a list of client fds somewhere, and every time through, FD_SET them into your structure. Then if they pop up as active and read fails, or if a write fails, shut them down, close them, and remove them from your list.

But... once in a while, select goes bonkers. It says you're selecting an invalid fd. Your program probably bombs on this, since select returning < 0 with errno != EINTR is not a good sign. You look and you look and you're handling everything properly! You sure don't re-add a deleted fd the next time around through the loop so what gives?

The problem is probably that you're not calling FD_ZERO on your fd_set structure every time around. Let's say you close a fd which is not the highest numbered one open, so max_fd doesn't change. Odds are, you'll start up with junk data in your fd_set which may well be the previous instance of it. It might just have the old fd's bit set, and select will go looking for it, even though you did not explicitly request it.

This seems to creep in when you get used to C++ semantics regarding objects having constructors and all of that and then you start using some good old C stuff again. You can't rely on what shows up there in your automatic variables. It might just be garbage.

Squashing that bug brings me one step closer to adding more cities to the scanner. Yay.