Wandering Thoughts archives

2006-01-18

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.

Whoops.

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

AnAcceptGotcha written at 01:04:23; Add Comment

2006-01-05

Is concurrency 'hard'?

Is concurrency hard? You can certainly find people arguing both sides of the issue if you look hard enough (mostly for rather than against). But I think the question may be blurring two things together that are worthwhile to separate: 'concurrency is difficult to learn and understand', and 'concurrency is tricky to implement correctly'.

For example, in his reaction to Joel Spolsky's Java Schools article, Tim Bray gives a little taxonomy of difficulty:

My experience differs from Joel's in another respect: Recursion is mildly hard. Closures and continuations are hard. Concurrency is very hard. I never found pointers hard at all.

For me, it really depends on what sense of 'hard' one means. Closures and continuations are somewhat mind-bending to understand, but I've found closures easy to use in programs. In a way closures are so easy to use that you may not realize that you are using them, because things 'just work'. (I haven't really used a language with full continuation support, but Python's limited version is pretty easy to use too.)

(Arguably closures (and Python's limited continuations) are only hard to understand if you insist on knowing how the magic works.)

So is concurrency hard? My belief is that concurrency isn't particularly difficult to understand, but it is definitely difficult to use. I think we have lots and lots of experimental evidence of the latter, and implicit experimental evidence of the former in that there are lots of people who think they understand concurrency well enough to use it.

It's possible that concurrency is harder to understand than I remember. I suspect that knowing something about computer architecture and assembly language helped me when I was learning about it, so I don't know how it would hit people without that sort of a background. (Although I think any graduate of a good CS undergrad program ought to have been exposed to both.)

IsConcurrencyHard written at 02:33:36; Add Comment


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

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