From ca45cf2ca598c61f5e3470cb406275f18bec8a13 Mon Sep 17 00:00:00 2001 From: Oldes Date: Sun, 10 Sep 2023 17:40:22 +0200 Subject: [PATCH] FEAT: allow extension to mark handle's context on free call and so prevent it from releasing --- src/core/m-gc.c | 3 +-- src/core/m-pools.c | 15 ++++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/src/core/m-gc.c b/src/core/m-gc.c index 68c0ad9021..0f5f2225c5 100644 --- a/src/core/m-gc.c +++ b/src/core/m-gc.c @@ -621,8 +621,7 @@ static void Mark_Series(REBSER *series, REBCNT depth); if (IS_MARK_HOB(hob)) UNMARK_HOB(hob); else { - Free_Hob(hob); - count++; + count += Free_Hob(hob); } } hob++; diff --git a/src/core/m-pools.c b/src/core/m-pools.c index 940389138e..aabc9bdf2b 100644 --- a/src/core/m-pools.c +++ b/src/core/m-pools.c @@ -604,7 +604,7 @@ const REBPOOLSPEC Mem_Pool_Spec[MAX_POOLS] = /*********************************************************************** ** -*/ void Free_Hob(REBHOB *hob) +*/ int Free_Hob(REBHOB *hob) /* ** Free a hob, returning its memory for reuse. ** @@ -613,19 +613,28 @@ const REBPOOLSPEC Mem_Pool_Spec[MAX_POOLS] = REBHSP spec; REBCNT idx = hob->index; - if( !IS_USED_HOB(hob) || hob->data == NULL ) return; + if( !IS_USED_HOB(hob) || hob->data == NULL ) return 0; spec = PG_Handles[idx]; //printf("HOB %p free mem: %p %i\n", hob, hob->data, spec.flags); if (spec.free) { - spec.free(spec.flags & HANDLE_REQUIRES_HOB_ON_FREE ? (void*)hob : (void*)hob->data); + if (spec.flags & HANDLE_REQUIRES_HOB_ON_FREE) { + spec.free((void*)hob); + // Although there are no references, the extension may still need the handle. + // If extension marks the hob, do not free it now. + if (IS_MARK_HOB(hob)) return 0; + } + else { + spec.free(hob->data); + } } CLEAR(hob->data, spec.size); FREE_MEM(hob->data); UNUSE_HOB(hob); Free_Node(HOB_POOL, (REBNOD *)hob); + return 1; }