bug#40194: Weak sets keep growing

Olivier Dion <[email protected]> Wed, 18 Feb 2026 12:30:07 -0500
Newsgroups gmane.lisp.guile.bugs
Message-ID <87fr6y7ye8.fsf@laura>
On Wed, 18 Feb 2026, Ludovic Court=C3=A8s <[email protected]> wrote:
> Hi Olivier,
>
> Olivier Dion <[email protected]> skribis:
[...]

> I totally lost track of the issue bug I=E2=80=99m glad you=E2=80=99re wor=
king on it.
>
> I only had a quick look but the fix and its explanation make sense to
> me.  Do you have ideas though as to why and when the previous approach
> =E2=80=9Cstopped working reliably=E2=80=9D as you wrote?

I guess this is internal to how libgc work.  From my understanding, and
debugging sessions, the finalized objects is marked when the callback is
called.  Thus, the sweep (after the finalizers?) will keep it.  I guess
this makes some sens since finalizers can re-introduce "dead" objects.
For obscure reasons, the objects is never finalized again, yet it
should.

My theory is, after the call to the finalizer, a flag is unset from the
object (done by libgc), thus removing our finalizer that we've just
installed.  The object is then simply garbaged collect as usual but we
just don't see it.  Would be interesting to track that object with a
watchpoint in GDB to see that in action.

> Do you have tests showing that this patch does indeed fix the problem?

Nope.  I did it manually with your reproducer and I can see the vaccuum
being called and the size of the weakset from %symbols is stable.  I
guess we could make a test in C to ensure that our async-gc callback is
indeed called.  But I fear spurious failure (rare) due to how
conservative garbage collection works.

> This is a quite sensitive piece of code so I=E2=80=99m worried about poss=
ible
> issues we did not anticipate. :-)

Same.  But TBH, I think this gets fixed by Whippet so I don't think we
need the fix that badly.  It would be nice however to have it for Guile
3 if we don't bump to Guile 4 with Whippet.

Thanks,
Olivier
--=20
Olivier Dion