#ifdef HAVE_MINGW
void io_add_event(io_t *io, io_cb_t cb, void *data, WSAEVENT event) {
- io_add(io, cb, data, -1, 0);
io->event = event;
+ io_add(io, cb, data, -1, 0);
}
#endif
fd_set writable;
while(running) {
- memcpy(&readable, &readfds, sizeof readable);
- memcpy(&writable, &writefds, sizeof writable);
struct timeval diff;
struct timeval *tv = get_time_remaining(&diff);
+ memcpy(&readable, &readfds, sizeof readable);
+ memcpy(&writable, &writefds, sizeof writable);
int fds = 0;
io->cb(io->data, IO_WRITE);
else if(FD_ISSET(io->fd, &readable))
io->cb(io->data, IO_READ);
+ else
+ continue;
+
+ /*
+ There are scenarios in which the callback will remove another io_t from the tree
+ (e.g. closing a double connection). Since splay_each does not support that, we
+ need to exit the loop now. That's okay, since any remaining events will get picked
+ up by the next select() call.
+ */
+ break;
}
}
#else
DWORD timeout_ms = tv ? (tv->tv_sec * 1000 + tv->tv_usec / 1000 + 1) : WSA_INFINITE;
if (!event_count) {
- LeaveCriticalSection(&mutex);
Sleep(timeout_ms);
- EnterCriticalSection(&mutex);
continue;
}
event_index++;
}
- LeaveCriticalSection(&mutex);
DWORD result = WSAWaitForMultipleEvents(event_count, events, FALSE, timeout_ms, FALSE);
- EnterCriticalSection(&mutex);
WSAEVENT event;
if (result >= WSA_WAIT_EVENT_0 && result < WSA_WAIT_EVENT_0 + event_count)
WSANETWORKEVENTS network_events;
if (WSAEnumNetworkEvents(io->fd, io->event, &network_events) != 0)
return false;
- if (network_events.lNetworkEvents & WRITE_EVENTS)
- io->cb(io->data, IO_WRITE);
if (network_events.lNetworkEvents & READ_EVENTS)
io->cb(io->data, IO_READ);
+ /*
+ The fd might be available for write too. However, if we already fired the read callback, that
+ callback might have deleted the io (e.g. through terminate_connection()), so we can't fire the
+ write callback here. Instead, we loop back and let the writable io loop above handle it.
+ */
}
}
#endif
return true;
}
-void event_flush_output(void) {
- for splay_each(io_t, io, &io_tree)
- if(io->flags & IO_WRITE)
- io->cb(io->data, IO_WRITE);
-}
-
void event_exit(void) {
running = false;
}