From: Arran Cudbard-Bell Date: Wed, 8 Apr 2020 16:14:47 +0000 (-0500) Subject: network: Pop messages before signalling workers to exit X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=809cf096fc273afed6af074757aeec6d788b57e7;p=thirdparty%2Ffreeradius-server.git network: Pop messages before signalling workers to exit --- diff --git a/src/lib/io/network.c b/src/lib/io/network.c index 839742c98fb..d5f96319da5 100644 --- a/src/lib/io/network.c +++ b/src/lib/io/network.c @@ -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);