Wandering Thoughts archives


A portability gotcha with accept()

Today's excitement came from trying to bring a local network daemon frontend up and running on a FreeBSD machine. It would spawn programs when you connected to it, but they always exited immediately after they printed their greeting banner; it was as if they were seeing an immediate end of file.

FreeBSD's ktrace revealed that when the spawned programs went to read from standard input, they got an EAGAIN result. Fortunately I've stubbed my toe on this one before: this is the exact symptom of your standard input being set non-blocking on you. But how was this happening?

(The amusing way to hit this is to have a program that sets its normal standard input to nonblocking and forgets to reset it back when it exits, and then run it from your shell. Your shell usually exits immediately, possibly quietly disappearing a terminal window with it.)

It turns out that on FreeBSD, accept() copies the properties of the server socket to the newly created socket; these properties include whether or not the socket is nonblocking. On Linux, this doesn't happen; the new socket is created with default properties. My server sockets were set nonblocking, just in case, so FreeBSD set up the new connections as nonblocking, which my frontend cheerfully passed to the newly spawned programs as their standard file descriptors.


FreeBSD's behavior turns out to be the traditional *BSD behavior, dating back to at least 4.0 BSD (we happen to have 4.0 BSD source online, since we're university packrats). Linux's behavior seems to be more Single Unix Standard compliant, based on their accept(2) manpage, although the ice may be thin.

(This is also covered in Dan Bernstein's Unix portability notes web page.)

Ironically, while Googling about this I found a linux-kernel thread about it here that I'm pretty sure I read at the time, back in 2000. (The thread has a reasonably good discussion of the whole issue.)

programming/AnAcceptGotcha written at 01:04:23; Add Comment

Page tools: See As Normal.
Login: Password:
Atom Syndication: Recent Pages, Recent Comments.

This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.