Subject: bug#72692: Emacs 31.05 (40eecd594ac) get SIGSEGV on Linux (Linux 6.6.45 Kde Wayland)

From: Pip Cet <[email-masked]>
Date: Mon, 19 Aug 2024 13:32:42 +0000

"Eli Zaretskii" <[email-masked]> writes:

>> Date: Mon, 19 Aug 2024 06:28:32 +0000
>> From: Pip Cet <[email-masked]>
>> Cc: [email-masked], [email-masked]
>>
>> "Eli Zaretskii" <[email-masked]> writes:
>>
>> > Here's one data point: this kind of problem has never, NEVER happened
>> > to me, although I display non-ASCII text in my Emacs sessions quite a
>> > lot.  So if what you describe is so trivially easy to trigger, how
>> > come it didn't happen to me, in all the years I'm using this code?
>>
>> It isn't trivially easy to trigger at all! To trigger it reliably, you
>> need to:
>>
>> * apply the patch so we don't reuse fontset table entries, which
>>   otherwise hides the bug
>
> But the OP didn't use that patch.

Indeed, and got rare (about once a day) crashes, even though they met
all other criteria for them.

> And your description sounded like
> the problem could happen quite frequently even without that patch.

The crashes are infrequent, since we will silently use the wrong fontset
rather than crashing if its ID has been reused.

Using the wrong fontset would be much more common, but lead to very
subtle bugs which I haven't seen (nor am I sure how they would show up).

>> * modify the mode line to use two new non-ASCII faces, at once, by
>>   inserting two characters provided by different fonts
>
> Why does it have to be the mode line?

It doesn't, but that gets us into the murky territory of what is and
isn't the same bug.

> why not buffer text?

Seems to cause the crash as well, via 'realize_default_face'

> Also, why do we need more than one non-ASCII face to trigger the
> problem?

I don't know.  As I said, I'm trying to understand that, but I think
it's a minor detail: we know the crash happens, we can reproduce it
(changing only things that make crashes more likely but shouldn't affect
correctness), we know why it's apparently rare (fontset slot reuse,
malloc() returning a freed face's block, the two non-ASCII-face thing).

>> * modify the right frame parameter (such as alpha-background) so that
>>   the basic faces are re-realized ('free_realized_face' is called for
>>   them), but 'free_realized_faces' is not.
>
> Basic faces are routinely freed and re-realized whenever we start the
> display iteration, see init_iterator.

> AFAIR, all you need to do for
> that is to customize some face -- doing so sets the face_change flag,
> and init_iterator will then normally free all the faces and realize
> them again.

... which won't trigger the bug, because it calls 'free_realized_faces'.
I specifically explained why 'free_realized_face' must be called
directly, not via (or after) 'free_realized_faces', to trigger the bug.

>> * be unlucky in your choice of malloc implementation
>
> "Unlucky" in what sense?

Have a malloc which returns a recently-freed block of appropriate size
for the next allocation.

> And if all the users of GNU/Linux (i.e. glibc) are thus "unlucky",
> this still leaves us with many potential victims.

Indeed, which is why we should fix the bug.

>> In particular, I'd like to understand why we need to use two non-ASCII
>> faces at once.
>
> Maybe I don't understand the question, but we need a new non-ASCII
> face each time we find a character for which existing non-ASCII faces
> don't have a glyph.

I meant why we need at least two non-ASCII faces to trigger the bug.

Here's a reproducer hibiscus.el which uses buffer text:

(while t
  (insert (concat (make-string 1 (floor (random 132000)))))
  (set-frame-parameter nil 'alpha-background 1.0)
  (sit-for 1.0))

It does, however, need at least two characters to crash, so the "why two
non-ASCII faces" problem remains.

Pip