Fix tinc event loop reentrancy from timeout handlers.
authorEtienne Dechamps <etienne@edechamps.fr>
Fri, 4 Jul 2014 23:23:05 +0000 (00:23 +0100)
committerEtienne Dechamps <etienne@edechamps.fr>
Sun, 6 Jul 2014 08:41:30 +0000 (09:41 +0100)
Commit 611217c96ec684799882cf330f40a0936131b6b5 introduced a regression
because it accidentally reordered the timeout handler calls and the
fdset setup code. This means that any io_add(), io_del() or io_set()
calls in timeout handlers would be ignored in the current event loop
iteration, resulting in erratic behavior.

The most visible symptom is when a metaconnection timeout occurs and the
connection is closed; the timeout handler closes the socket but it still
ends up in the select() call, typically resulting in the following
crash:

    Error while waiting for input: Bad file descriptor

src/event.c

index f34974206b1dac9c140105f4b67230749c5a036b..cb710a06b60b07d6af7752bf68c4f9c0c4fd7745 100644 (file)
@@ -256,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;