diff --git a/src/event.c b/src/event.c index 60d357d4..59b96e37 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 diff --git a/src/list.h b/src/list.h index 0437bd92..b0e7a845 100644 --- a/src/list.h +++ b/src/list.h @@ -79,6 +79,12 @@ extern void list_delete_list(list_t *); extern void list_foreach(list_t *, list_action_t); extern void list_foreach_node(list_t *, list_action_node_t); +/* + Iterates over a list. + + CAUTION: while this construct supports deleting the current item, + it does *not* support deleting *other* nodes while iterating on the list. + */ #define list_each(type, item, list) (type *item = (type *)1; item; item = NULL) for(list_node_t *node = (list)->head, *next; item = node ? node->data : NULL, next = node ? node->next : NULL, node; node = next) #endif /* __TINC_LIST_H__ */ diff --git a/src/splay_tree.h b/src/splay_tree.h index 58488707..3ddf2172 100644 --- a/src/splay_tree.h +++ b/src/splay_tree.h @@ -106,6 +106,12 @@ extern splay_node_t *splay_search_closest_greater_node(splay_tree_t *, const voi extern void splay_foreach(const splay_tree_t *, splay_action_t); extern void splay_foreach_node(const splay_tree_t *, splay_action_t); +/* + Iterates over a tree. + + CAUTION: while this construct supports deleting the current item, + it does *not* support deleting *other* nodes while iterating on the tree. + */ #define splay_each(type, item, tree) (type *item = (type *)1; item; item = NULL) for(splay_node_t *node = (tree)->head, *next; item = node ? node->data : NULL, next = node ? node->next : NULL, node; node = next) #endif