Subject: Re: bug#46256: [feature/native-comp] AOT eln files ignored if run from build tree

From: Pip Cet <[email-masked]>
Date: Sun, 7 Mar 2021 21:27:57 +0000

On Sun, Mar 7, 2021 at 8:17 PM Andrea Corallo via Bug reports for GNU
Emacs, the Swiss army knife of text editors <[email-masked]>
wrote:
> Eli Zaretskii <[email-masked]> writes:
> >> From: Andrea Corallo <[email-masked]>
> >> Cc: [email-masked], [email-masked]
> >> Date: Sun, 07 Mar 2021 18:53:50 +0000
> What I think is going on here:
>
> The same .eln file is loaded two times, we detect that and try to reuse
> the same compilation unit (the Lisp object) instead of a new one.
>
> We keep a pointer to the compilation unit representing the .eln file in
> each .eln.  Here we read it and we have it into 'saved_cu', we try to
> dereference it and extract the CU with XNATIVE_COMP_UNIT but something
> goes wrong.
>
> This object might have been GC'ed for some reason and we might be
> looking at the same GC issue I've seen on 32bit wide-int (my guess).
> *If* this is the case the question is: why is the CU GC'ed?

Why wouldn't it be? I'm trying to follow along here :-)

What I'm thinking is the CU got GC'ed, which is perfectly okay, but we
never set its COMP_UNIT_SYM pointer to Qnil. Then we dlopen() the same
file again, get the old handle, read the stale COMP_UNIT_SYM pointer,
and dereference it.

We should verify that the CU is indeed a different PVEC type now
(ideally, PVEC_FREE), and then do something like the attached patch,
shouldn't we?

Pip
From 23496d8793c475b451a0d8fc35b2781e9c4746a9 Mon Sep 17 00:00:00 2001
From: Pip Cet <[email-masked]>
Date: Sun, 7 Mar 2021 21:26:29 +0000
Subject: [PATCH] Fix a GC issue (bug#46256)

* src/alloc.c (cleanup_vector): Clear the comp unit pointer in the
dynamically-loaded object.
---
 src/alloc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/src/alloc.c b/src/alloc.c
index af08336177070..e039441ea826c 100644
--- a/src/alloc.c
+++ b/src/alloc.c
@@ -3155,9 +3155,12 @@ cleanup_vector (struct Lisp_Vector *vector)
   else if (NATIVE_COMP_FLAG
 	   && PSEUDOVECTOR_TYPEP (&vector->header, PVEC_NATIVE_COMP_UNIT))
     {
+#define COMP_UNIT_SYM "comp_unit"
       struct Lisp_Native_Comp_Unit *cu =
 	PSEUDOVEC_STRUCT (vector, Lisp_Native_Comp_Unit);
       eassert (cu->handle);
+      Lisp_Object *saved_cu = dynlib_sym (cu->handle, COMP_UNIT_SYM);
+      *saved_cu = Qnil;
       dynlib_close (cu->handle);
     }
   else if (NATIVE_COMP_FLAG
-- 
2.30.1