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

From: Helmut Eller <[email-masked]>
Date: Sat, 28 Jun 2025 22:21:59 +0200

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.

> The way finalizers are currently run on the master branch when they
> appear in weak tables, even if there is no chance that the entry that
> references them is ever collected, makes them pretty much unusable on
> that branch, in my book.  Making them usable with --with-mps=yes isn't
> much of a priority for me, TBH, as code using them would break when we
> compile without MPS support.

Putting finalizers in a weak hashtable sounds exotic.  I suppose there
should be tests for this.

> (I considered using finalizers for font finalization; it works, but
> would break if a strong reference to the font is mistaken for a weak one
> and fails to keep alive the font).

There is some "hardcoded" finalization code in cleanup_vector for
PVEC_FONT.  Maybe you could use that instead of Lisp_Finalizers.

Helmut

diff --git a/src/alloc.c b/src/alloc.c
index 07ca8474bf3..f784bd91da7 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -5965,6 +5965,10 @@ garbage_collect (void)
       mark_object (BVAR (nextb, undo_list));
     }
 
+  /* Must happen after all other marking and before gc_sweep.  */
+  mark_and_sweep_weak_table_contents ();
+  eassert (weak_hash_tables == NULL);
+
   /* Now pre-sweep finalizers.  Here, we add any unmarked finalizers
      to doomed_finalizers so we can run their associated functions
      after GC.  It's important to scan finalizers at this stage so
@@ -5975,10 +5979,6 @@ garbage_collect (void)
   queue_doomed_finalizers (&doomed_finalizers, &finalizers);
   mark_finalizer_list (&doomed_finalizers);
 
-  /* Must happen after all other marking and before gc_sweep.  */
-  mark_and_sweep_weak_table_contents ();
-  eassert (weak_hash_tables == NULL);
-
   eassert (mark_stack_empty_p ());
 
   gc_sweep ();