]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Don't crash on exit in threaded mode when using rlm_radius
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 14 Dec 2019 11:38:21 +0000 (18:38 +0700)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Sat, 14 Dec 2019 11:38:21 +0000 (18:38 +0700)
src/lib/server/request.c
src/lib/server/request.h
src/modules/rlm_radius/rlm_radius_udp.c

index 8911b50ee70f0557485900e40f61ed38f4c69116..cdc965e2ce96970046a815cba1495370d49d204d 100644 (file)
@@ -266,6 +266,23 @@ REQUEST *request_alloc(TALLOC_CTX *ctx)
        return request;
 }
 
+/** Allocate a request that's not in the free list
+ *
+ * This can be useful if modules need a persistent request for their own purposes
+ * which needs to be outside of the normal free list, so that it can be freed
+ * when the module requires, not when the thread destructor runs.
+ */
+REQUEST *request_alloc_local(TALLOC_CTX *ctx)
+{
+       REQUEST *request;
+
+       MEM(request = talloc_zero(ctx, REQUEST));
+
+       request_init(request);
+
+       return request;
+}
+
 static REQUEST *request_init_fake(REQUEST *request, REQUEST *fake)
 {
        fake->number = request->child_number++;
index c23597c76d31e2e4cd911fe0b8ee337d50868069..9cf6756e109cdf261b8f3ee2a8cde72882fe1149 100644 (file)
@@ -177,6 +177,8 @@ struct fr_request_s {
 
 REQUEST                *request_alloc(TALLOC_CTX *ctx);
 
+REQUEST                *request_alloc_local(TALLOC_CTX *ctx);
+
 REQUEST                *request_alloc_fake(REQUEST *parent, fr_dict_t const *namespace);
 
 REQUEST                *request_alloc_detachable(REQUEST *request, fr_dict_t const *namespace);
index fc2a79de89a72ebd80d049adfc51863165533a69..0451cf824de4985c90c0147043854bf8ceb3ca42 100644 (file)
@@ -2597,7 +2597,15 @@ static fr_connection_state_t _conn_open(UNUSED fr_event_list_t *el, void *h, voi
 
                u = talloc_zero(c, fr_io_request_t);
 
-               request = request_alloc(u);
+               /*
+                *      Allocate outside of the free list.
+                *      There appears to be an issue where
+                *      the thread destructor runs too
+                *      early, and frees the freelist's
+                *      head before the module destructor
+                *      runs.
+                */
+               request = request_alloc_local(u);
                request->async = talloc_zero(request, fr_async_t);
                talloc_const_free(request->name);
                request->name = talloc_strdup(request, c->module_name);