Subject: Re: bug#72165: 31.0.50; Intermittent crashing with recent emacs build

From: Eli Zaretskii <[email-masked]>
Date: Mon, 29 Jul 2024 14:45:52 +0300

> From: Dima Kogan <[email-masked]>
> Cc: [email-masked]
> Date: Sun, 28 Jul 2024 19:50:52 -0700
> 
> Alright. After some flailing I was able to make it crash with rr, so now
> I can see EVERYTHING. rr is truly a miracle, and figuring this out
> without it would have been impossible.

Thanks for persevering.

> Then on line 12177 we check if we're exceeding message-log-max, and if
> so, delete some stuff from the *Messages*.
> 
>   if (FIXNATP (Vmessage_log_max))
>     {
>       scan_newline (Z, Z_BYTE, BEG, BEG_BYTE,
>                     -XFIXNAT (Vmessage_log_max) - 1, false);
>       del_range_both (BEG, BEG_BYTE, PT, PT_BYTE, false);
>     }
> 
> In the failing sequence we delete some of the non-ascii characters. So
> the byte-char offset changes: it was 4 or 8 bytes, and it becomes 0 or 4
> bytes. At this point we're still correct. But very shortly after this,
> on line 12205 we restore the oldpoint into the current point. Since we
> just deleted stuff from the BEGINNING of the buffer, the oldpoint
> doesn't point to the same thing as before. Restoring it directly is
> wrong, but this normally doesn't cause crashes. The thing that causes
> crashing is that sometimes the byte-char offset in oldpoint is no longer
> correct, and we fail the consistency checks in redisplay_window().

I'm confused by the last part of your description.  The code which
resets point to 'oldpoint' is this:

      if (point_at_end)
	TEMP_SET_PT_BOTH (Z, Z_BYTE);
      else
	/* We can't do Fgoto_char (oldpoint) because it will run some
           Lisp code.  */
	TEMP_SET_PT_BOTH (marker_position (oldpoint),
			  marker_byte_position (oldpoint));

IOW, it uses 'oldpoint', which is a marker, not a simple number.  It
was initialized like this:

      oldpoint = message_dolog_marker1;
      set_marker_restricted_both (oldpoint, Qnil, PT, PT_BYTE);

Since 'oldpoint' is a marker, it should have been moved by
del_range_both so that it still points to the same text.  Moreover,
the char <-> byte correspondence was not supposed to be disrupted by
that.

So I think something else is at work here.  Can you show the data you
collected during the rr session?  Specifically, what are the character
and byte positions of 'oldpoint' before the call to del_range_both,
how many characters and bytes were deleted by del_range_both, and what
are the character and byte position of 'oldpoint' when we call
TEMP_SET_PT_BOTH in the snippet I show above?

One possibility is that the value of 'oldpoint' gets overwritten
somehow between the place it is set and the place it is used to
restore point.  But in that case we need to find the code which
overwrites it.