igrigorik/agent — Issue #5: Race condition in selector
Author: nate
Created: 2012-03-02 19:31:40+00:00
State: open

There is a race condition in the Kernel#select method beween the [yield and the call to Selector#select](https://github.com/igrigorik/agent/blob/master/lib/agent.rb#L23-24). More specifically, the race condition is between [the check to see if a channel is immediately ready for use](https://github.com/igrigorik/agent/blob/master/lib/agent/selector.rb#L25) and [when callbacks are registered](https://github.com/igrigorik/agent/blob/master/lib/agent/selector.rb#L48-49). If a channel becomes available for reading or writing in between these then the callbacks may never fire despite the conditions being met at the time of the call to Selector#select.

In order to fix this race condition with minimum code changes you'd need to freeze the channels as they are added in the case method such that they're frozen between the check to see if it's immediately available and until the callbacks are added. There could be significant delay there, however, so I don't think freezing them there is a good idea.

You would still need to freeze them in order to synchronize the channels either way, I think. A better way to handle this might be to have the case method preserve the order that the selector callbacks are added and not check whether the channel is immediately available. We could then freeze the channels in the select method check them for immediate availability in the order that now has been preserved in the case, handle the default case if it's there, add the notification callbacks to the channels, then unfreeze the channels.

I'm not sure how else we could eliminate that race condition, but I'm open to ideas.