X-Git-Url: https://tinc-vpn.org/git/browse?p=tinc;a=blobdiff_plain;f=src%2Fevent.c;h=59b96e37dc3f7d3c7fa80ed96d27be1326a915c9;hp=0e4e2bdfa2aada1c62b44eea0a0e521e78d70454;hb=390d25f0b80dd7418e147de3561c70461628574d;hpb=611217c96ec684799882cf330f40a0936131b6b5 diff --git a/src/event.c b/src/event.c index 0e4e2bdf..59b96e37 100644 --- a/src/event.c +++ b/src/event.c @@ -35,7 +35,7 @@ static const long READ_EVENTS = FD_READ | FD_ACCEPT | FD_CLOSE; static const long WRITE_EVENTS = FD_WRITE | FD_CONNECT; static DWORD event_count = 0; #endif -static volatile bool running; +static bool running; static int io_compare(const io_t *a, const io_t *b) { #ifndef HAVE_MINGW @@ -72,9 +72,11 @@ void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags) { io->fd = fd; #ifdef HAVE_MINGW - io->event = WSACreateEvent(); - if (io->event == WSA_INVALID_EVENT) - abort(); + if (io->fd != -1) { + io->event = WSACreateEvent(); + if (io->event == WSA_INVALID_EVENT) + abort(); + } event_count++; #endif io->cb = cb; @@ -87,10 +89,19 @@ void io_add(io_t *io, io_cb_t cb, void *data, int fd, int flags) { abort(); } +#ifdef HAVE_MINGW +void io_add_event(io_t *io, io_cb_t cb, void *data, WSAEVENT event) { + io->event = event; + io_add(io, cb, data, -1, 0); +} +#endif + void io_set(io_t *io, int flags) { if (flags == io->flags) return; io->flags = flags; + if (io->fd == -1) + return; #ifndef HAVE_MINGW if(flags & IO_READ) @@ -119,7 +130,7 @@ void io_del(io_t *io) { io_set(io, 0); #ifdef HAVE_MINGW - if (WSACloseEvent(io->event) == FALSE) + if (io->fd != -1 && WSACloseEvent(io->event) == FALSE) abort(); event_count--; #endif @@ -245,10 +256,10 @@ bool event_loop(void) { 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; @@ -274,6 +285,16 @@ bool event_loop(void) { 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 @@ -283,9 +304,7 @@ bool event_loop(void) { 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; } @@ -317,9 +336,7 @@ bool event_loop(void) { 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) @@ -334,25 +351,23 @@ bool event_loop(void) { if (!io) abort(); - 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); + if (io->fd == -1) { + io->cb(io->data, 0); + } else { + 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); + } } #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; }