Robert Norris wrote:
[ Resending, as there's been no discussion, and I'm afraid it may have been missed. I need an answer soon. Thanks :) ]
Greg Ames and I are working on an Apache 2.0 patch to do keep-alive reads in an event-loop (to free up threads blocked on keep-alive connections). I expect we will run into some of what you are now observing and dig into the code and learn it in detail.
My comments that follow are just a little more reliable than speculation... (and if someone wants to step in with definitive answers, please do so...).
I'm considering moving my application to APR over my own internal utility library (APR is much nicer), so I've started implementing a simple descriptor event loop to get a feel for it. However, I've run up against a couple of deficiencies in the API and I'm not sure where to go from here.
I'm working with APR 0.9.4. I'm only working off the headers to know what's possible, so if there's an obvious piece of documentation somewhere that I've missed, please just point me there.
1. I don't see a way to update the requested events for a fd that is already in a pollset. I can update pollfd->reqevents, but those changes never make it to the underlying pollfd structure (Unix).
It seems the only way to do this is to call pollset_remove(), then pollset_add() again. This is obviously suboptimal, as pollset_remove() does a search.
I think your observation is correct on both counts. The pollset API is basically a first cut implementation and I would expect optimizations like you describe would not be in the implementation.
pollset_remove() could be optimised if an index into the pollfd array
was held in apr_pollfd_t (or something similar, as this is
platform-dependent). We'd lose the ability to store a single descriptor
in a pollset twice,
I am not sure the ability to store a single descriptor twice is an issue. A pollfd array would need to be dynamically sizeable. We would not want to place artificial limits on the number of fs's in the pollset (unlike the array passed in to select() for example).
I think that is correct. The biggest user of APR (Apache 2.0) just does a read when the socket goes readable. Either the read works and there are bytes to handle, or it fails because the client close'd its end of the connection.but it would get rid of the search, which would make the addition of a new function to update the underlying pollfd trivial (no search required).
2. I need to be able to figure out when a socket has been closed by the peer. The usual way to do this is to check how many bytes are waiting to be read when the socket goes readable. I've used both the FIONREAD ioctl and the MSG_PEEK flag to recv before to do this. It doesn't seem that the APR socket API supports any mechanism like this.
Getting a POLLHUP event from the poll call also seems to work in some places, but its not really portable[1], and APR does it differently again.
I agree this is not portable.
Bill