ping

On Wed, 2021-09-01 at 22:51 +0200, Martijn van Duren wrote:
> Bluhm asked me to rethink the freeing strategy.
> Here's the end result.
> 
> On Mon, 2021-08-30 at 12:03 +0200, Martijn van Duren wrote:
> > 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  1 Sep 2021 20:51:09 -0000
> @@ -270,10 +270,12 @@ agentx_reset(struct agentx *ax)
>       struct agentx_session *axs, *tsas;
>       struct agentx_request *axr;
>       struct agentx_get *axg;
> +     int axfree = ax->ax_free;
>  
>       ax_free(ax->ax_ax);
>       ax->ax_ax = NULL;
>       ax->ax_fd = -1;
> +     ax->ax_free = 1;
>  
>       ax->ax_cstate = AX_CSTATE_CLOSE;
>  
> @@ -289,52 +291,52 @@ agentx_reset(struct agentx *ax)
>               TAILQ_REMOVE(&(ax->ax_getreqs), axg, axg_ax_getreqs);
>       }
>  
> -     if (ax->ax_dstate == AX_DSTATE_CLOSE) {
> -             agentx_free_finalize(ax);
> -             return;
> -     }
> +     if (ax->ax_dstate == AX_DSTATE_OPEN)
> +             agentx_start(ax);
>  
> -     agentx_start(ax);
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>  }
>  
>  void
>  agentx_free(struct agentx *ax)
>  {
>       struct agentx_session *axs, *tsas;
> +     int axfree;
>  
>       if (ax == NULL)
>               return;
>  
> -     if (ax->ax_dstate == AX_DSTATE_CLOSE) {
> -/* Malloc throws abort on invalid pointers as well */
> +     axfree = ax->ax_free;
> +     ax->ax_free = 1;
> +
> +     /* Malloc throws abort on invalid pointers as well */
> +     if (ax->ax_dstate == AX_DSTATE_CLOSE)
>               agentx_log_ax_fatalx(ax, "%s: double free", __func__);
> -     }
>       ax->ax_dstate = AX_DSTATE_CLOSE;
>  
> -     if (!TAILQ_EMPTY(&(ax->ax_sessions))) {
> -             TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions,
> -                 tsas) {
> -                     if (axs->axs_dstate != AX_DSTATE_CLOSE)
> -                             agentx_session_free(axs);
> -             }
> -     } else
> +     TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions, tsas) {
> +             if (axs->axs_dstate != AX_DSTATE_CLOSE)
> +                     agentx_session_free(axs);
> +     }
> +     if (!axfree)
>               agentx_free_finalize(ax);
>  }
>  
>  static void
>  agentx_free_finalize(struct agentx *ax)
>  {
> -#ifdef AX_DEBUG
> -     if (ax->ax_dstate != AX_DSTATE_CLOSE)
> -             agentx_log_ax_fatalx(ax, "%s: agentx not closing",
> -                 __func__);
> -     if (!TAILQ_EMPTY(&(ax->ax_sessions)))
> -             agentx_log_ax_fatalx(ax, "%s: agentx still has sessions",
> -                 __func__);
> -     if (!RB_EMPTY(&(ax->ax_requests)))
> -             agentx_log_ax_fatalx(ax,
> -                 "%s: agentx still has pending requests", __func__);
> -#endif
> +     struct agentx_session *axs, *taxs;
> +
> +     ax->ax_free = 0;
> +
> +     TAILQ_FOREACH_SAFE(axs, &(ax->ax_sessions), axs_ax_sessions, taxs)
> +             agentx_session_free_finalize(axs);
> +
> +     if (!TAILQ_EMPTY(&(ax->ax_sessions)) ||
> +         !RB_EMPTY(&(ax->ax_requests)) ||
> +         ax->ax_dstate != AX_DSTATE_CLOSE)
> +             return;
>  
>       ax_free(ax->ax_ax);
>       ax->ax_nofd(ax, ax->ax_cookie, 1);
> @@ -477,6 +479,7 @@ agentx_session_close_finalize(struct ax_
>       struct agentx_session *axs = cookie;
>       struct agentx *ax = axs->axs_ax;
>       struct agentx_context *axc, *tsac;
> +     int axfree = ax->ax_free;
>  
>  #ifdef AX_DEBUG
>       if (axs->axs_cstate != AX_CSTATE_WAITCLOSE)
> @@ -492,19 +495,19 @@ agentx_session_close_finalize(struct ax_
>       }
>  
>       axs->axs_cstate = AX_CSTATE_CLOSE;
> +     ax->ax_free = 1;
>  
>       agentx_log_axs_info(axs, "closed");
>  
>       TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, tsac)
>               agentx_context_reset(axc);
>  
> -     if (axs->axs_dstate == AX_DSTATE_CLOSE)
> -             agentx_session_free_finalize(axs);
> -     else {
> -             if (ax->ax_cstate == AX_CSTATE_OPEN)
> -                     if (agentx_session_start(axs) == -1)
> -                             return -1;
> -     }
> +     if (ax->ax_cstate == AX_CSTATE_OPEN &&
> +         axs->axs_dstate == AX_DSTATE_OPEN)
> +             agentx_session_start(axs);
> +     if (!axfree)
> +             agentx_free_finalize(ax);
> +             
>       return 0;
>  }
>  
> @@ -512,10 +515,16 @@ void
>  agentx_session_free(struct agentx_session *axs)
>  {
>       struct agentx_context *axc, *tsac;
> +     struct agentx *ax;
> +     int axfree;
>  
>       if (axs == NULL)
>               return;
>  
> +     ax = axs->axs_ax;
> +     axfree = ax->ax_free;
> +     ax->ax_free = 1;
> +
>       if (axs->axs_dstate == AX_DSTATE_CLOSE)
>               agentx_log_axs_fatalx(axs, "%s: double free", __func__);
>  
> @@ -529,44 +538,45 @@ agentx_session_free(struct agentx_sessio
>                       agentx_context_free(axc);
>       }
>  
> -     if (axs->axs_cstate == AX_CSTATE_CLOSE)
> -             agentx_session_free_finalize(axs);
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>  }
>  
>  static void
>  agentx_session_free_finalize(struct agentx_session *axs)
>  {
>       struct agentx *ax = axs->axs_ax;
> +     struct agentx_context *axc, *taxc;
>  
> -#ifdef AX_DEBUG
> -     if (axs->axs_cstate != AX_CSTATE_CLOSE)
> -             agentx_log_axs_fatalx(axs, "%s: free without closing",
> -                 __func__);
> -     if (!TAILQ_EMPTY(&(axs->axs_contexts)))
> -             agentx_log_axs_fatalx(axs,
> -                 "%s: agentx still has contexts", __func__);
> -#endif
> +     TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, taxc)
> +             agentx_context_free_finalize(axc);
> +
> +     if (!TAILQ_EMPTY(&(axs->axs_contexts)) ||
> +         axs->axs_cstate != AX_CSTATE_CLOSE ||
> +         axs->axs_dstate != AX_DSTATE_CLOSE)
> +             return;
>  
>       TAILQ_REMOVE(&(ax->ax_sessions), axs, axs_ax_sessions);
>       free(axs->axs_descr.aos_string);
>       free(axs);
> -
> -     if (TAILQ_EMPTY(&(ax->ax_sessions)) && ax->ax_dstate == AX_DSTATE_CLOSE)
> -             agentx_free_finalize(ax);
>  }
>  
>  static void
>  agentx_session_reset(struct agentx_session *axs)
>  {
>       struct agentx_context *axc, *tsac;
> +     struct agentx *ax = axs->axs_ax;
> +     int axfree = ax->ax_free;
> +
> +     ax->ax_free = 1;
>  
>       axs->axs_cstate = AX_CSTATE_CLOSE;
>  
>       TAILQ_FOREACH_SAFE(axc, &(axs->axs_contexts), axc_axs_contexts, tsac)
>               agentx_context_reset(axc);
>  
> -     if (axs->axs_dstate == AX_DSTATE_CLOSE)
> -             agentx_session_free_finalize(axs);
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>  }
>  
>  struct agentx_context *
> @@ -714,15 +724,20 @@ static void
>  agentx_context_free_finalize(struct agentx_context *axc)
>  {
>       struct agentx_session *axs = axc->axc_axs;
> +     struct agentx_region *axr, *taxr;
> +     struct agentx_agentcaps *axa, *taxa;
> +
> +     TAILQ_FOREACH_SAFE(axa, &(axc->axc_agentcaps), axa_axc_agentcaps, taxa)
> +             agentx_agentcaps_free_finalize(axa);
> +     TAILQ_FOREACH_SAFE(axr, &(axc->axc_regions), axr_axc_regions, taxr)
> +             agentx_region_free_finalize(axr);
>  
> -#ifdef AX_DEBUG
> -     if (axc->axc_dstate != AX_DSTATE_CLOSE)
> -             agentx_log_axc_fatalx(axc, "%s: unexpected context free",
> -                 __func__);
> -#endif
>       if (!TAILQ_EMPTY(&(axc->axc_regions)) ||
> -         !TAILQ_EMPTY(&(axc->axc_agentcaps)))
> +         !TAILQ_EMPTY(&(axc->axc_agentcaps)) ||
> +         axc->axc_cstate != AX_CSTATE_CLOSE ||
> +         axc->axc_dstate != AX_DSTATE_CLOSE)
>               return;
> +
>       TAILQ_REMOVE(&(axs->axs_contexts), axc, axc_axs_contexts);
>       free(axc->axc_name.aos_string);
>       free(axc);
> @@ -733,6 +748,10 @@ agentx_context_reset(struct agentx_conte
>  {
>       struct agentx_agentcaps *axa, *tsaa;
>       struct agentx_region *axr, *tsar;
> +     struct agentx *ax = axc->axc_axs->axs_ax;
> +     int axfree = ax->ax_free;
> +
> +     ax->ax_free = 1;
>  
>       axc->axc_cstate = AX_CSTATE_CLOSE;
>       axc->axc_sysuptimespec.tv_sec = 0;
> @@ -743,8 +762,8 @@ agentx_context_reset(struct agentx_conte
>       TAILQ_FOREACH_SAFE(axr, &(axc->axc_regions), axr_axc_regions, tsar)
>               agentx_region_reset(axr);
>  
> -     if (axc->axc_dstate == AX_DSTATE_CLOSE)
> -             agentx_context_free_finalize(axc);
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>  }
>  
>  struct agentx_agentcaps *
> @@ -883,6 +902,7 @@ agentx_agentcaps_close_finalize(struct a
>       struct agentx_context *axc = axa->axa_axc;
>       struct agentx_session *axs = axc->axc_axs;
>       struct agentx *ax = axs->axs_ax;
> +     int axfree = ax->ax_free;
>  
>  #ifdef AX_DEBUG
>       if (axa->axa_cstate != AX_CSTATE_WAITCLOSE)
> @@ -899,41 +919,43 @@ agentx_agentcaps_close_finalize(struct a
>       }
>  
>       axa->axa_cstate = AX_CSTATE_CLOSE;
> +     ax->ax_free = 1;
>  
>       agentx_log_axc_info(axc, "agentcaps %s: closed",
>           ax_oid2string(&(axa->axa_oid)));
>  
> -     if (axa->axa_dstate == AX_DSTATE_CLOSE) {
> -             agentx_agentcaps_free_finalize(axa);
> -             return 0;
> -     } else {
> -             if (axc->axc_cstate == AX_CSTATE_OPEN) {
> -                     if (agentx_agentcaps_start(axa) == -1)
> -                             return -1;
> -             }
> -     }
> +     if (axc->axc_cstate == AX_CSTATE_OPEN &&
> +         axa->axa_dstate == AX_DSTATE_OPEN)
> +             agentx_agentcaps_start(axa);
> +
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>       return 0;
>  }
>  
>  void
>  agentx_agentcaps_free(struct agentx_agentcaps *axa)
>  {
> +     struct agentx *ax = axa->axa_axc->axc_axs->axs_ax;
> +     int axfree;
> +
>       if (axa == NULL)
>               return;
>  
> +     axfree = ax->ax_free;
> +     ax->ax_free = 1;
> +
>       if (axa->axa_dstate == AX_DSTATE_CLOSE)
>               agentx_log_axc_fatalx(axa->axa_axc, "%s: double free",
>                   __func__);
>  
>       axa->axa_dstate = AX_DSTATE_CLOSE;
>  
> -     if (axa->axa_cstate == AX_CSTATE_OPEN) {
> -             if (agentx_agentcaps_close(axa) == -1)
> -                     return;
> -     }
> +     if (axa->axa_cstate == AX_CSTATE_OPEN)
> +             agentx_agentcaps_close(axa);
>  
> -     if (axa->axa_cstate == AX_CSTATE_CLOSE)
> -             agentx_agentcaps_free_finalize(axa);
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>  }
>  
>  static void
> @@ -941,27 +963,24 @@ agentx_agentcaps_free_finalize(struct ag
>  {
>       struct agentx_context *axc = axa->axa_axc;
>  
> -#ifdef AX_DEBUG
>       if (axa->axa_dstate != AX_DSTATE_CLOSE ||
>           axa->axa_cstate != AX_CSTATE_CLOSE)
> -             agentx_log_axc_fatalx(axc, "%s: unexpected free", __func__);
> -#endif
> +             return;
>  
>       TAILQ_REMOVE(&(axc->axc_agentcaps), axa, axa_axc_agentcaps);
>       free(axa->axa_descr.aos_string);
>       free(axa);
> -
> -     if (axc->axc_dstate == AX_DSTATE_CLOSE)
> -             agentx_context_free_finalize(axc);
>  }
>  
>  static void
>  agentx_agentcaps_reset(struct agentx_agentcaps *axa)
>  {
> +     struct agentx *ax = axa->axa_axc->axc_axs->axs_ax;
> +
>       axa->axa_cstate = AX_CSTATE_CLOSE;
>  
> -     if (axa->axa_dstate == AX_DSTATE_CLOSE)
> -             agentx_agentcaps_free_finalize(axa);
> +     if (!ax->ax_free)
> +             agentx_free_finalize(ax);
>  }
>  
>  struct agentx_region *
> @@ -1166,6 +1185,7 @@ agentx_region_close_finalize(struct ax_p
>       struct agentx_context *axc = axr->axr_axc;
>       struct agentx_session *axs = axc->axc_axs;
>       struct agentx *ax = axs->axs_ax;
> +     int axfree = ax->ax_free;
>  
>  #ifdef AX_DEBUG
>       if (axr->axr_cstate != AX_CSTATE_WAITCLOSE)
> @@ -1181,21 +1201,19 @@ agentx_region_close_finalize(struct ax_p
>               return -1;
>       }
>  
> +     ax->ax_free = 1;
>       axr->axr_priority = AX_PRIORITY_DEFAULT;
>       axr->axr_cstate = AX_CSTATE_CLOSE;
>  
>       agentx_log_axc_info(axc, "region %s: closed",
>           ax_oid2string(&(axr->axr_oid)));
>  
> -     if (axr->axr_dstate == AX_DSTATE_CLOSE) {
> -             agentx_region_free_finalize(axr);
> -             return 0;
> -     } else {
> -             if (axc->axc_cstate == AX_CSTATE_OPEN) {
> -                     if (agentx_region_start(axr) == -1)
> -                             return -1;
> -             }
> -     }
> +     if (axc->axc_cstate == AX_CSTATE_OPEN &&
> +         axr->axr_dstate == AX_DSTATE_OPEN)
> +             agentx_region_start(axr);
> +
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>       return 0;
>  }
>  
> @@ -1204,10 +1222,16 @@ agentx_region_free(struct agentx_region 
>  {
>       struct agentx_index *axi, *tsai;
>       struct agentx_object *axo, *tsao;
> +     struct agentx *ax;
> +     int axfree;
>  
>       if (axr == NULL)
>               return;
>  
> +     ax = axr->axr_axc->axc_axs->axs_ax;
> +     axfree = ax->ax_free;
> +     ax->ax_free = 1;
> +
>       if (axr->axr_dstate == AX_DSTATE_CLOSE)
>               agentx_log_axc_fatalx(axr->axr_axc, "%s: double free",
>                   __func__);
> @@ -1224,37 +1248,33 @@ agentx_region_free(struct agentx_region 
>                       agentx_object_free(axo);
>       }
>  
> -     if (axr->axr_cstate == AX_CSTATE_OPEN) {
> -             if (agentx_region_close(axr) == -1)
> -                     return;
> -     }
> +     if (axr->axr_cstate == AX_CSTATE_OPEN)
> +             agentx_region_close(axr);
>  
> -     if (axr->axr_cstate == AX_CSTATE_CLOSE)
> -             agentx_region_free_finalize(axr);
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>  }
>  
>  static void
>  agentx_region_free_finalize(struct agentx_region *axr)
>  {
>       struct agentx_context *axc = axr->axr_axc;
> +     struct agentx_index *axi, *taxi;
> +     struct agentx_object *axo, *taxo;
>  
> -#ifdef AX_DEBUG
> -     if (axr->axr_dstate != AX_DSTATE_CLOSE)
> -             agentx_log_axc_fatalx(axc, "%s: unexpected free", __func__);
> -#endif
> +     TAILQ_FOREACH_SAFE(axo, &(axr->axr_objects), axo_axr_objects, taxo)
> +             agentx_object_free_finalize(axo);
> +     TAILQ_FOREACH_SAFE(axi, &(axr->axr_indices), axi_axr_indices, taxi)
> +             agentx_index_free_finalize(axi);
>  
>       if (!TAILQ_EMPTY(&(axr->axr_indices)) ||
> -         !TAILQ_EMPTY(&(axr->axr_objects)))
> -             return;
> -
> -     if (axr->axr_cstate != AX_CSTATE_CLOSE)
> +         !TAILQ_EMPTY(&(axr->axr_objects)) ||
> +         axr->axr_cstate != AX_CSTATE_CLOSE ||
> +         axr->axr_dstate != AX_DSTATE_CLOSE)
>               return;
>  
>       TAILQ_REMOVE(&(axc->axc_regions), axr, axr_axc_regions);
>       free(axr);
> -
> -     if (axc->axc_dstate == AX_DSTATE_CLOSE)
> -             agentx_context_free_finalize(axc);
>  }
>  
>  static void
> @@ -1262,17 +1282,20 @@ agentx_region_reset(struct agentx_region
>  {
>       struct agentx_index *axi, *tsai;
>       struct agentx_object *axo, *tsao;
> +     struct agentx *ax = axr->axr_axc->axc_axs->axs_ax;
> +     int axfree = ax->ax_free;
>  
>       axr->axr_cstate = AX_CSTATE_CLOSE;
>       axr->axr_priority = AX_PRIORITY_DEFAULT;
> +     ax->ax_free = 1;
>  
>       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)
>               agentx_object_reset(axo);
>  
> -     if (axr->axr_dstate == AX_DSTATE_CLOSE)
> -             agentx_region_free_finalize(axr);
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>  }
>  
>  struct agentx_index *
> @@ -1739,10 +1762,16 @@ agentx_index_free(struct agentx_index *a
>  {
>       size_t i;
>       struct agentx_object *axo;
> +     struct agentx *ax;
> +     int axfree;
>  
>       if (axi == NULL)
>               return;
>  
> +     ax = axi->axi_axr->axr_axc->axc_axs->axs_ax;
> +     axfree = ax->ax_free;
> +     ax->ax_free = 1;
> +
>       if (axi->axi_dstate == AX_DSTATE_CLOSE)
>               agentx_log_axc_fatalx(axi->axi_axr->axr_axc,
>                   "%s: double free", __func__);
> @@ -1761,8 +1790,8 @@ agentx_index_free(struct agentx_index *a
>  
>       if (axi->axi_cstate == AX_CSTATE_OPEN)
>               (void) agentx_index_close(axi);
> -     else if (axi->axi_cstate == AX_CSTATE_CLOSE)
> -             agentx_index_free_finalize(axi);
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>  }
>  
>  static void
> @@ -1770,33 +1799,26 @@ agentx_index_free_finalize(struct agentx
>  {
>       struct agentx_region *axr = axi->axi_axr;
>  
> -#ifdef AX_DEBUG
> -     if (axi->axi_dstate != AX_DSTATE_CLOSE)
> -             agentx_log_axc_fatalx(axr->axr_axc, "%s: unexpected free",
> -                 __func__);
> -     if (axi->axi_cstate != AX_CSTATE_CLOSE)
> -             agentx_log_axc_fatalx(axr->axr_axc,
> -                 "%s: free without deallocating", __func__);
> -#endif
> -
> -     if (axi->axi_objectlen != 0)
> +     if (axi->axi_cstate != AX_CSTATE_CLOSE ||
> +         axi->axi_dstate != AX_DSTATE_CLOSE ||
> +         axi->axi_objectlen != 0)
>               return;
>  
>       TAILQ_REMOVE(&(axr->axr_indices), axi, axi_axr_indices);
>       ax_varbind_free(&(axi->axi_vb));
>       free(axi->axi_object);
>       free(axi);
> -     if (axr->axr_dstate == AX_DSTATE_CLOSE)
> -             agentx_region_free_finalize(axr);
>  }
>  
>  static void
>  agentx_index_reset(struct agentx_index *axi)
>  {
> +     struct agentx *ax = axi->axi_axr->axr_axc->axc_axs->axs_ax;
> +
>       axi->axi_cstate = AX_CSTATE_CLOSE;
>  
> -     if (axi->axi_dstate == AX_DSTATE_CLOSE)
> -             agentx_index_free_finalize(axi);
> +     if (!ax->ax_free)
> +             agentx_free_finalize(ax);
>  }
>  
>  static int
> @@ -1842,6 +1864,7 @@ agentx_index_close_finalize(struct ax_pd
>       struct agentx_session *axs = axc->axc_axs;
>       struct agentx *ax = axs->axs_ax;
>       struct ax_pdu_response *resp = &(pdu->ap_payload.ap_response);
> +     int axfree = ax->ax_free;
>  
>  #ifdef AX_DEBUG
>       if (axi->axi_cstate != AX_CSTATE_WAITCLOSE)
> @@ -1895,16 +1918,17 @@ agentx_index_close_finalize(struct ax_pd
>       }
>  
>       axi->axi_cstate = AX_CSTATE_CLOSE;
> +     ax->ax_free = 1;
>  
>       agentx_log_axc_info(axc, "index %s: deallocated",
>           ax_oid2string(&(axi->axi_vb.avb_oid)));
>  
> -     if (axi->axi_dstate == AX_DSTATE_CLOSE) {
> -             agentx_index_free_finalize(axi);
> -     } else if (axr->axr_cstate == AX_CSTATE_OPEN) {
> -             if (agentx_index_start(axi) == -1)
> -                     return -1;
> -     }
> +     if (axr->axr_cstate == AX_CSTATE_OPEN &&
> +         axi->axi_dstate == AX_DSTATE_OPEN)
> +             agentx_index_start(axi);
> +
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>       return 0;
>  }
>  
> @@ -2198,8 +2222,6 @@ agentx_object_finalize(struct ax_pdu *pd
>               agentx_log_axc_info(axc, "object %s (%s %s): %s",
>                   oids, flags ? "instance" : "region", ax_oid2string(&oid),
>                   ax_error2string(pdu->ap_payload.ap_response.ap_error));
> -             if (axo->axo_dstate == AX_DSTATE_CLOSE)
> -                     return agentx_object_close_finalize(NULL, axo);
>               return 0;
>       }
>       axo->axo_cstate = AX_CSTATE_OPEN;
> @@ -2227,15 +2249,18 @@ agentx_object_lock(struct agentx_object 
>  static void
>  agentx_object_unlock(struct agentx_object *axo)
>  {
> +     struct agentx *ax = axo->axo_axr->axr_axc->axc_axs->axs_ax;
> +
>  #ifdef AX_DEBUG
>       if (axo->axo_lock == 0)
>               agentx_log_axc_fatalx(axo->axo_axr->axr_axc,
>                   "%s: axo_lock == 0", __func__);
>  #endif
>       axo->axo_lock--;
> -     if (axo->axo_lock == 0 && axo->axo_dstate == AX_DSTATE_CLOSE &&
> -         axo->axo_cstate == AX_CSTATE_CLOSE)
> -             agentx_object_free_finalize(axo);
> +     if (axo->axo_lock == 0) {
> +             if (!ax->ax_free)
> +                     agentx_free_finalize(ax);
> +     }
>  }
>  
>  static int
> @@ -2316,6 +2341,7 @@ agentx_object_close_finalize(struct ax_p
>       char oids[1024];
>       uint8_t flags = 1;
>       size_t i;
> +     int axfree = ax->ax_free;
>  
>  #ifdef AX_DEBUG
>       if (axo->axo_cstate != AX_CSTATE_WAITCLOSE)
> @@ -2355,13 +2381,13 @@ agentx_object_close_finalize(struct ax_p
>                   flags ? "instance" : "region", ax_oid2string(&oid));
>       }
>  
> -     if (axo->axo_dstate == AX_DSTATE_CLOSE)
> -             agentx_object_free_finalize(axo);
> -     else {
> -             if (axr->axr_cstate == AX_CSTATE_OPEN)
> -                     if (agentx_object_start(axo) == -1)
> -                             return -1;
> -     }
> +     ax->ax_free = 1;
> +     if (axr->axr_cstate == AX_CSTATE_OPEN &&
> +         axo->axo_dstate == AX_DSTATE_OPEN)
> +             agentx_object_start(axo);
> +
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>  
>       return 0;
>  }
> @@ -2369,21 +2395,26 @@ agentx_object_close_finalize(struct ax_p
>  void
>  agentx_object_free(struct agentx_object *axo)
>  {
> +     struct agentx *ax;
> +     int axfree;
> +
>       if (axo == NULL)
>               return;
>  
> +     ax = axo->axo_axr->axr_axc->axc_axs->axs_ax;
> +     axfree = ax->ax_free;
> +     ax->ax_free = 1;
> +
>       if (axo->axo_dstate == AX_DSTATE_CLOSE)
>               agentx_log_axc_fatalx(axo->axo_axr->axr_axc,
>                   "%s: double free", __func__);
>  
>       axo->axo_dstate = AX_DSTATE_CLOSE;
>  
> -     if (axo->axo_cstate == AX_CSTATE_OPEN) {
> -             if (agentx_object_close(axo) == -1)
> -                     return;
> -     }
> -     if (axo->axo_cstate == AX_CSTATE_CLOSE)
> -             agentx_object_free_finalize(axo);
> +     if (axo->axo_cstate == AX_CSTATE_OPEN)
> +             agentx_object_close(axo);
> +     if (!axfree)
> +             agentx_free_finalize(ax);
>  }
>  
>  static void
> @@ -2395,21 +2426,10 @@ agentx_object_free_finalize(struct agent
>       size_t i, j;
>       int found;
>  
> -#ifdef AX_DEBUG
> -     if (axo->axo_dstate != AX_DSTATE_CLOSE)
> -             agentx_log_axc_fatalx(axo->axo_axr->axr_axc,
> -                 "%s: unexpected free", __func__);
> -#endif
> -
> -     if (axo->axo_lock != 0) {
> -#ifdef AX_DEBUG
> -             if (TAILQ_EMPTY(&(ax->ax_getreqs)))
> -                     agentx_log_axc_fatalx(axo->axo_axr->axr_axc,
> -                         "%s: %s axo_lock == %u", __func__,
> -                         ax_oid2string(&(axo->axo_oid)), axo->axo_lock);
> -#endif
> +     if (axo->axo_dstate != AX_DSTATE_CLOSE ||
> +         axo->axo_cstate != AX_CSTATE_CLOSE ||
> +         axo->axo_lock != 0)
>               return;
> -     }
>  
>       RB_REMOVE(axc_objects, &(axo->axo_axr->axr_axc->axc_objects), axo);
>       TAILQ_REMOVE(&(axo->axo_axr->axr_objects), axo, axo_axr_objects);
> @@ -2429,9 +2449,6 @@ agentx_object_free_finalize(struct agent
>                           "%s: object not found in index", __func__);
>  #endif
>               axo->axo_index[i]->axi_objectlen--;
> -             if (axo->axo_index[i]->axi_dstate == AX_DSTATE_CLOSE &&
> -                 axo->axo_index[i]->axi_cstate == AX_CSTATE_CLOSE)
> -                     agentx_index_free_finalize(axo->axo_index[i]);
>       }
>  
>       free(axo);
> @@ -2440,10 +2457,12 @@ agentx_object_free_finalize(struct agent
>  static void
>  agentx_object_reset(struct agentx_object *axo)
>  {
> +     struct agentx *ax = axo->axo_axr->axr_axc->axc_axs->axs_ax;
> +
>       axo->axo_cstate = AX_CSTATE_CLOSE;
>  
> -     if (axo->axo_dstate == AX_DSTATE_CLOSE)
> -             agentx_object_free_finalize(axo);
> +     if (!ax->ax_free)
> +             agentx_free_finalize(ax);
>  }
>  
>  static int
> Index: agentx_internal.h
> ===================================================================
> RCS file: /cvs/src/lib/libagentx/agentx_internal.h,v
> retrieving revision 1.2
> diff -u -p -r1.2 agentx_internal.h
> --- agentx_internal.h 26 Oct 2020 16:02:16 -0000      1.2
> +++ agentx_internal.h 1 Sep 2021 20:51:09 -0000
> @@ -38,6 +38,7 @@ struct agentx {
>       int ax_fd;
>       enum agentx_cstate ax_cstate;
>       enum agentx_dstate ax_dstate;
> +     int ax_free;            /* Freeing already planned */
>       struct ax *ax_ax;
>       TAILQ_HEAD(, agentx_session) ax_sessions;
>       TAILQ_HEAD(, agentx_get) ax_getreqs;
> 


Reply via email to