if (netio->deallocated) {
/*
* If we have deallocated handler list elements, reuse
* the first one.
*/
elt = netio->deallocated;
netio->deallocated = elt->next;
} else {
/*
* Allocate a new one.
*/
elt = (netio_handler_list_type *) region_alloc(
netio->region, sizeof(netio_handler_list_type));
}
if (have_timeout && minimum_timeout.tv_sec < 0) {
/*
* On negative timeout for a handler, immediately
* dispatch the timeout event without checking for
* other events.
*/
if (timeout_handler && (timeout_handler->event_types & NETIO_EVENT_TIMEOUT)) {
timeout_handler->event_handler(netio, timeout_handler, NETIO_EVENT_TIMEOUT);
}
return result;
}
/*
* Clear the cached current_time (pselect(2) may block for
* some time so the cached value is likely to be old).
*/
netio->have_current_time = 0;
if (rc == 0) {
/*
* No events before the minimum timeout expired.
* Dispatch to handler if interested.
*/
if (timeout_handler && (timeout_handler->event_types & NETIO_EVENT_TIMEOUT)) {
timeout_handler->event_handler(netio, timeout_handler, NETIO_EVENT_TIMEOUT);
}
} else {
/*
* Dispatch all the events to interested handlers
* based on the fd_sets. Note that a handler might
* deinstall itself, so store the next handler before
* calling the current handler!
*/
assert(netio->dispatch_next == NULL);
for (elt = netio->handlers; elt && rc; ) {
netio_handler_type *handler = elt->handler;
netio->dispatch_next = elt->next;
if (handler->fd != -1 && handler->pfd != -1) {
netio_event_types_type event_types
= NETIO_EVENT_NONE;
if ((fds[handler->pfd].revents & POLLIN)) {
event_types |= NETIO_EVENT_READ;
}
if ((fds[handler->pfd].revents & POLLOUT)) {
event_types |= NETIO_EVENT_WRITE;
}
if ((fds[handler->pfd].revents &
(POLLNVAL|POLLHUP|POLLERR))) {
/* closed/error: give a read event,
* or otherwise, a write event */
if((handler->event_types&NETIO_EVENT_READ))
event_types |= NETIO_EVENT_READ;
else if((handler->event_types&NETIO_EVENT_WRITE))
event_types |= NETIO_EVENT_WRITE;
}