Subject: bug#13864: 24.3.50; emacsclient -t loops when connected to emacs server running in X11

From: [email-masked] (Ashish SHUKLA)
Date: Mon, 01 Apr 2013 22:15:46 +0530

On Mon, 25 Mar 2013 12:56:06 +0200, Eli Zaretskii <[email-masked]> said:
>> From: [email-masked] (Ashish SHUKLA)
>> Cc: [email-masked]
>> Date: Mon, 25 Mar 2013 14:58:08 +0530
>> 
>> >  (gdb) break dispnew.c:2623 if vpos == 5
>> 
>> s/vpos/row/ I guess

> Yes, sorry.

>> Please refer to the attached gdb output with annotations prefixed with '=====> '.

> OK, the reason for constant redrawing of the emacsclient TTY frame is
> that Emacs thinks that frame is "garbaged" (i.e. its display is
> completely outdated and should be redrawn):

>   Hardware watchpoint 6: ((struct glyph_row *) 0x196e500)->enabled_p

>   Old value = 1
>   New value = 0
>   clear_glyph_matrix_rows (matrix=0x1825f00, start=5, end=28) at dispnew.c:728
>   728	  for (; start < end; ++start)
>   #0  clear_glyph_matrix_rows (matrix=0x1825f00, start=5, end=28) at dispnew.c:728
>   #1  0x0000000000417028 in clear_glyph_matrix (matrix=0x1825f00) at dispnew.c:747
>   #2  0x00000000004175bc in clear_current_matrices (f=0x117ac48) at dispnew.c:795
>   #3  0x000000000044c348 in clear_garbaged_frames () at xdisp.c:10611
>   #4  0x0000000000450de9 in redisplay_internal () at xdisp.c:12925

> The function clear_garbaged_frames does this:

>       FOR_EACH_FRAME (tail, frame)
> 	{
> 	  struct frame *f = XFRAME (frame);

> 	  if (FRAME_VISIBLE_P (f) && FRAME_GARBAGED_P (f)) <<<<<<<<<
> 	    {
> 	      if (f->resized_p)
> 		{
> 		  redraw_frame (f);
f-> force_flush_display_p = 1;
> 		}
> 	      clear_current_matrices (f); <<<<<<<<<<<<<<<<<<<<<<<<<<<
> 	      changed_count++;
f-> garbaged = 0;
f-> resized_p = 0;
> 	    }
> 	}

> And the call to clear_current_matrices invalidates the record of
> what's currently displayed on the TTY frame, and therefore causes
> constant redrawing of that frame.

> So the question now is: which code sets the frame's 'garbaged' flag?
> To find out, do this in GDB:

>  (gdb) tbreak dispnew.c:4861 if vpos == 5
>  (gdb) c

> The breakpoint is here:

>       else
> 	/* Make sure we are in the right row, otherwise cursor movement
> 	   with cmgoto might use `ch' in the wrong row.  */
> 	cursor_to (f, vpos, 0);

>       make_current (desired_matrix, current_matrix, vpos); <<<<<<<<<<<<<<<<
>       return;
>     }

> Note that the breakpoint is temporary ("tbreak"), so it will only
> break once.  This is to avoid hitting it again, after you set the
> watchpoint below, because we only need this breakpoint to find out the
> address of the TTY frame structure, whose 'garbaged' flag we want to
> watch.

> When this breakpoint breaks, type these commands:

>  (gdb) p f
>  $1 = (struct frame *) 0x12345678
>  (gdb) watch ((struct frame *) 0x12345678)->garbaged
>  (gdb) commands
>> if ((struct frame *) 0x12345678)->garbaged == 1
>> bt
>> end
>> continue
>  (gdb)

> Again, the value of f will be different in your case; use whatever GDB
> shows in your case for the following 'watch' command.

> Now do whatever is needed to cause Emacs flicker, and the backtrace
> from the watchpoint should show who sets the garbaged flag of the TTY
> frame.

Please refer to the attached output. I'm not sure if it's for the right frame
(i.e. "garbaged" flag monitored for X11 frame, or emacsclient frame).

Let me know if you like me to take it again.

Thanks
-- 
Ashish SHUKLA

“Many of the convicted thieves Parker has met began their life of crime after
taking college Computer Science courses.” (Roger Rapoport, "Programs for
Plunder", Omni, March 1981)

Sent from my Emacs