Subject: Re: bug#75322: SAFE_ALLOCA assumed to root Lisp_Objects/SSDATA(string)

From: Eli Zaretskii <[email-masked]>
Date: Sun, 05 Jan 2025 11:32:12 +0200

> Date: Sun, 05 Jan 2025 09:04:06 +0000
> From: Pip Cet <[email-masked]>
> Cc: [email-masked], [email-masked]
> 
> "Eli Zaretskii" <[email-masked]> writes:
> > we should be able to use without restrictions static variables whose
> > values are Lisp strings.
> 
> Without staticpro?  That makes no sense whatsoever to me.  It's not true
> for either garbage collector.  Do you expect MPS to scan the entire
> data/bss segment ambiguously?

That's not relevant to the issue at hand, which was about the
following snippet:

    static Lisp_Object unmarked;
                       ^^^^^^
    unmarked = string;
    ... trigger GC here ...
    puts (SDATA (unmarked);

That 'unmarked' is a static variable is not relevant, because the
issue is the pointer to the text data of 'string', which value we put
int 'unmarked'.

> >> Which might be in a register and not survive until GC is triggered.
> >
> > A Lisp_Object variable will survive.  Its pointer will be updated if
> > needed to point to the new location of the data.  Thus, using the
> 
> MPS never changes the value of an automatic variable.

Exactly!

> > Lisp_Object variable is always safe, but the pointer to its data must
> > be updated after a potential GC.
> >
> >> >> > The below is indeed unsafe:
> >> >> >
> >> >> >   char *p = SDATA (unmarked);
> >> >> >   ... trigger GC here ...
> >> >> >   puts (p);
> >> >>
> >> >> Right now, that's safe for MPS, but not for the old GC, correct?
> >> >
> >> > If GC moves string data, then it is not safe, period.  Does MPS move
> >> > string data?
> >>
> >> MPS does not move string data if there is a stack variable pointing to
> >> it.  It does in other cases.  This is why it's safe for MPS.  The old
> >> GC, IIUC, is less forgiving.
> >
> > The conclusion is that the above is NOT safe, because in some cases
> > the data could move.  Which was what I said from the get-go.
> 
> The conclusion is incorrect.  The code is safe if MPS is in use, and we
> rely on that.

No, we do NOT, and should NOT, rely on that!  Because you yourself say
above that MPS will move the string data in some cases.

> The idea behind MPS is that you write code as above, which is safe when
> MPS is in use, rather than attempting to avoid GC, which is fragile at
> best (see call_process) and impossible in multi-threaded systems.

I don't suggest to avoid GC.  I suggest that where GC _can_ happen, we
must reinitialize the pointer to string data after GC.

Otherwise, what was all that discussion about what call_process does
with the strings in the args[] array?  If GC cannot change the data
pointer to SDATA, then why should we care about GC in that function?

> You seem to fundamentally disagree with me about how MPS works.  We need
> to resolve that difference one way or another before we can continue any
> GC-related discussions.

I have a much larger issue here: this discussion produces an enormous
number of long messages without actually leading anywhere.  Maybe I'm
too stupid to discuss this, but I cannot keep it going like that, it
eats up all my free time (of which I don't have too much to be gin
with).