Subject: bug#78917: feature/igc [PATCH] Avoid chaining finalizers together

From: Pip Cet <[email-masked]>
Date: Sun, 29 Jun 2025 19:02:27 +0000

"Daniel Colascione" <[email-masked]> writes:

> Pip Cet via "Bug reports for GNU Emacs, the Swiss army knife of text editors" <[email-masked]> writes:
>
>> "Helmut Eller" <[email-masked]> writes:
>>
>>> On Sat, Jun 28 2025, Pip Cet wrote:
>>>
>>>> "Helmut Eller" <[email-masked]> writes:
>>>>
>>>>> Lisp_Finalizers are currently chained together in a doubly linked list.
>>>>> This prevents them from being collected.  I propose that we simply don't
>>>>> use this list with MPS.
>>>>
>>>> See https://lists.gnu.org/archive/html/emacs-devel/2025-05/msg00468.html
>>>
>>> :-)
>>>
>>>> and bug#77338.
>>>
>>> It seems that the problem with finalizers as value in a weak hashtable
>>> could be fixed by calling mark_and_sweep_weak_table_contents before
>>> queue_doomed_finalizers as in the patch below.
>
> Ouch.  That branch of the discussion of bug#77338 slipped past me.
> Thanks for bringing it up.

> Gut feeling is that the solution is some kind of iterated walk over
> finalizers and weak tables until we reach a fixed point?  Let me think
> it over.

Thanks, that'd be great!

My approach was to do the combined iteration by keeping finalizers in a
weak hash table (a weak set).

1. mark all weak hash tables, including the finalizer table, until we
hit a fixed point
2. condemn unmarked finalizers; remember that somewhere
3. mark all condemned finalizers strongly
4. repeat step 1
5. sweep unmarked weak hash table entries (there are none in the
finalizer table)
6. run condemned finalizers and remove them from the table

However, I admit that using a weak hash table to keep the finalizers in
is problematic, because we might have to shrink it at some point.  Also,
no working code here, so maybe my approach was entirely wrong.

If we can fix this, we could change font finalization to use Lisp
finalizers, I think.

>> No, that's not the right fix: a finalizer function can still refer to
>> weak hash tables (the finalizer itself is not a weak object), so we
>> can't sweep the weak hash tables until all finalizers have been marked.
>>
>> This is solvable, but it requires more effort than exchanging those two
>> calls.
>>
>> However, I'm not sure we should fix the traditional GC code to be better
>> than what MPS can do :-)
>
> Emacs 31 is going to live a long time and igc won't be its default GC.

Agreed.  I'm just saying we don't need to define to the last detail how
finalizers behave wrt weak hash tables, it's better if there is some
slack there so other GC implementations can do their job.

Similarly, we should probably deprecate key-and-value strongness in
Emacs generally, and remove the hack that makes it "work" in
feature/igc.

Pip