]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
network: Pop messages before signalling workers to exit
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 8 Apr 2020 16:14:47 +0000 (11:14 -0500)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Wed, 8 Apr 2020 16:15:21 +0000 (11:15 -0500)
src/lib/io/network.c

index 839742c98fb7f05645678993c5baf79e5063dd19..d5f96319da5f3f9d495fd73efc8022725dab15b9 100644 (file)
@@ -1297,6 +1297,29 @@ int fr_network_destroy(fr_network_t *nr)
                talloc_free(sockets);
        }
 
+
+       /*
+        *      Clean up all outstanding replies.
+        *
+        *      We can't do this after signalling the
+        *      workers to close, because they free
+        *      their message sets, and we end up
+        *      getting random use-after-free errors
+        *      as there's a race between the network
+        *      popping replies, and the workers
+        *      freeing their message sets.
+        *
+        *      This isn't perfect, and we might still
+        *      lose some replies, but it's good enough
+        *      for now.
+        *
+        *      @todo - call transport "done" for the reply, so that
+        *      it knows the replies are done, too.
+        */
+       while ((cd = fr_heap_pop(nr->replies)) != NULL) {
+               fr_message_done(&cd->m);
+       }
+
        /*
         *      Signal the workers that we're closing
         *
@@ -1316,16 +1339,6 @@ int fr_network_destroy(fr_network_t *nr)
                }
        }
 
-       /*
-        *      Clean up all of the replies.
-        *
-        *      @todo - call transport "done" for the reply, so that
-        *      it knows the replies are done, too.
-        */
-       while ((cd = fr_heap_pop(nr->replies)) != NULL) {
-               fr_message_done(&cd->m);
-       }
-
        (void) fr_event_pre_delete(nr->el, fr_network_pre_event, nr);
        (void) fr_event_post_delete(nr->el, fr_network_post_event, nr);
        fr_event_fd_delete(nr->el, nr->signal_pipe[0], FR_EVENT_FILTER_IO);