Selector not blocking on select

Ill try to put some client code together that can make it easier to reproduce the behavior.

If what you’r saying is correct, then isnt it impossibel to do a workaround to this problem? In theory the addNewConnections method could be called while the selector thread was out in the select loop, and had last returned a 0-set. If the new connection had then been closed before being processed it wouldnt be registered. Without the register() call (which seems to reset internal state) the selector would be in the same situation as in my test code. It of course takes a good portion of bad luck to have the thread scheduler “pause” the selector thread out in the select loop, but thats not something you can guard your code against.

Without non-blocking your write calls would block until the data had been written. the selector giving a writable key doesnt have to mean there is space in the write buffer to write all your data.

[quote]Unless otherwise specified, a write operation will return only after writing all of the r requested bytes. Some types of channels, depending upon their state, may write only some of the bytes or possibly none at all. A socket channel in non-blocking mode, for example, cannot write any more bytes than are free in the socket’s output buffer.
[/quote]
That really breaks the concept of multiplexing io where you just want to process what can be processed immidiatly. Im not sure on the behavior of socketchannel.read in blocking mode (and the api doc isnt specific on that) but I would assume it block until buffer is filled.

Ok, looking back on my connection code I wrote before with NIO, I also use non-blocking sockets. so…nevermind. :slight_smile:

I would like to add, however, that the way I have my server set up, I have one thread waiting for connections and when connections are accepted the new channel is put on a queue that the ‘Client input’ thread will read from when it is woken up, and I was not seeing the behavior you described. The server started the ‘Accept Listener’ thread, and the client processor thread, and the client processor thread would select on a channel with zero channels registered with it, and when a new client connects, the accepter thread puts the channel on the client processor thread’s queue, and then calls wakeup() on the selector…this causes the client listener thead to wakeup (zero channels will be in the select list, however), check the queue for new connections, register new connections with the selector, and then process the ready channels (still zero!). Then, the loop goes back again and the select will block until there is client activity (or another client connects causing the wakeup() to be called). I’ve never ran across the behavior you described, maybe I should post some code to compare notes?

-Chris

In my code I have a similar setup. I have my ConnectionListener object that also waits for new connections and then give them to the “client processer”/ConnectionWorker object, through the same queue&wakeup mechanism you have describes. That wakeup doesnt cause any problems.

The problem seems to be when wakeup is called and the thread then returns to .select() without having performed some operations that modify its internal state. Also note that it seems that the behavior is almost impossibel to create (ive done it a few times) with conections comming from same machine as the one hosting the server. I’ll be using my sparetime the next days to make an application for a friend but after that Ill get coded some extra test classes so that other can try to reproduce the issue (with the intention of making a bug report)

Ok, then if modifying the internal state of the selector is the issue, shouldn’t you register the channel that was put on the queue after you call wakup()? However, what i’m thinking now is that if you have 2 connectinos come in at the same time, you could potentially call wakeup() twice (2 new clients) before the selector thread wakes up and processes the connections in the queue…and when it does wake up, it will add two connections to the selector, and then go back to select() but since the second wakeup was issued during the second connect, that means that the selector will wakeup again, but this time there are no connections in the queue to add to the selector to modify the internal state. (Is this an accurate description of what could happen?) In this case, i’m not really sure what you should do except maybe as a work around you have a flag that you set that marks if wakeup was already called, and in the selector thread, you clear the flag…hmmm Well if it’s fixed in 1.5 even better heh

-Chris