Subject: bug#20808: 24.5; Emacs looping with 100% CPU at line 15287 (?) of xdisp.c

From: Eli Zaretskii <[email-masked]>
Date: Tue, 16 Jun 2015 18:03:22 +0300

> From: [email-masked] (N. Jackson)
> Cc: [email-masked]
> Date: Mon, 15 Jun 2015 12:42:57 -0300
> 
> It's not clear to me if GDB prints out the statement it just executed or
> the statement that it will execute next

The latter.

> The variables don't change, and after a few spins through the loop,
> I set watchpoints on them and `finish' and there was no sign of them
> changing after about five minutes, after which I did a C-c.

As expected.  That's why it infloops.

> For the Fedora 21 build (the variables don't change):
> 
>     (gdb) p it.current
>     $11 = {pos = {charpos = 0, bytepos = 0}, overlay_string_index = 0, string_pos = {charpos = 0, bytepos = 0}, dpvec_index = 0}
>     (gdb) p it.current_y  
>     $12 = 0
>     (gdb) p it.max_ascent 
>     $13 = 0
>     (gdb) p it.max_descent
>     $14 = 0

These values make no sense.  I guess the optimized binary lies to GDB.

> For my build (again the variables don't change):
> 
>     (gdb) p it.current
>     $20 = {pos = {charpos = 2840, bytepos = 2841}, overlay_string_index = -1, string_pos = {charpos = -1, bytepos = -1}, dpvec_index = -1}
>     (gdb) p it.current_y
>     $21 = 270
>     (gdb) p it.ascent 
>     $22 = 11
>     (gdb) p it.descent
>     $23 = 3
>     (gdb) p it.method
>     $24 = GET_FROM_BUFFER
>     (gdb) p start_y
>     $25 = 270
>     (gdb) p ZV
>     $34 = 2840
>     (gdb) p current_buffer->zv
>     $35 = 2840

This makes much more sense.

> I hope this helps, and I await further instructions should further
> debugging be worthwhile.

Yes, it helps.  Please try the patch below.  If it solves the problem,
I will install it shortly.  Please try both an optimized and a
non-optimized build, if you can afford that.

diff --git a/src/xdisp.c b/src/xdisp.c
index 7c15330..1e2f1b26 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -15094,7 +15094,8 @@ enum
 	    RESTORE_IT (&it, &it, it1data);
 	    move_it_by_lines (&it, 1);
 	    SAVE_IT (it1, it, it1data);
-	  } while (line_bottom_y (&it1) - start_y < amount_to_scroll);
+	  } while (IT_CHARPOS (it) < ZV
+		   && line_bottom_y (&it1) - start_y < amount_to_scroll);
 	}
 
       /* If STARTP is unchanged, move it down another screen line.  */