I missed this one before, since apparently it doesn't show up with
MALLOC_OPTIONS set to "S", but it does if it is empty.

This probably effects relayd if the admin has it enabled en then
disables it via a "relayctl reload". However, I'm not able to
reproduce it there and even if it can be triggered, chances of
that happening in real life are slim to none.

I think the comment should explain enough.

OK?

martijn@

Index: agentx.c
===================================================================
RCS file: /cvs/src/lib/libagentx/agentx.c,v
retrieving revision 1.10
diff -u -p -r1.10 agentx.c
--- agentx.c    2 Jun 2021 08:40:09 -0000       1.10
+++ agentx.c    30 Aug 2021 10:03:08 -0000
@@ -1262,16 +1262,29 @@ agentx_region_reset(struct agentx_region
 {
        struct agentx_index *axi, *tsai;
        struct agentx_object *axo, *tsao;
+       int dofree = 1;
 
        axr->axr_cstate = AX_CSTATE_CLOSE;
        axr->axr_priority = AX_PRIORITY_DEFAULT;
 
-       TAILQ_FOREACH_SAFE(axi, &(axr->axr_indices), axi_axr_indices, tsai)
+       TAILQ_FOREACH_SAFE(axi, &(axr->axr_indices), axi_axr_indices, tsai) {
                agentx_index_reset(axi);
-       TAILQ_FOREACH_SAFE(axo, &(axr->axr_objects), axo_axr_objects, tsao)
+               dofree = 0;
+       }
+       TAILQ_FOREACH_SAFE(axo, &(axr->axr_objects), axo_axr_objects, tsao) {
                agentx_object_reset(axo);
+               dofree = 0;
+       }
 
-       if (axr->axr_dstate == AX_DSTATE_CLOSE)
+       /*
+        * If there were children they already freed axr for us via
+        * agentx_index_finalize().
+        * This construction is needed because agentx_region_free()
+        * calls the *_close functions on itself and its children, but the close
+        * confirmations might be received out of order and we can't free the
+        * region if there's still children active.
+        */
+       if (dofree && axr->axr_dstate == AX_DSTATE_CLOSE)
                agentx_region_free_finalize(axr);
 }
 


Reply via email to