X-Git-Url: https://www.tinc-vpn.org/git/browse?a=blobdiff_plain;f=src%2Fevent.c;h=858e1d9d96d7d0fc497a845ee98203f939b0c747;hb=1672dbd66b619f84cb86950298ad89df93e1dcba;hp=60d357d4a09b6898ef0b0483c498e144d639bc50;hpb=04fc19112da5e7fcefefcf6e490987cdcfb6f620;p=tinc diff --git a/src/event.c b/src/event.c index 60d357d4..858e1d9d 100644 --- a/src/event.c +++ b/src/event.c @@ -285,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 @@ -347,10 +357,13 @@ bool event_loop(void) { 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