all messages for Emacs-related lists mirrored at yhetil.org
 help / color / mirror / code / Atom feed
From: Eli Zaretskii <eliz@gnu.org>
To: ashish.is@lostca.se (Ashish SHUKLA)
Cc: 13864@debbugs.gnu.org
Subject: bug#13864: 24.3.50; emacsclient -t loops when connected to emacs server running in X11
Date: Sun, 24 Mar 2013 21:54:04 +0200	[thread overview]
Message-ID: <83k3ow376r.fsf@gnu.org> (raw)
In-Reply-To: <864ng3hae1.fsf@chateau.d.if>

> From: ashish.is@lostca.se (Ashish SHUKLA)
> Cc: 13864@debbugs.gnu.org
> Date: Fri, 22 Mar 2013 18:14:22 +0530
> 
> > That's strange, I'm probably missing something.  Not terribly
> > important (it's tangential to the issue I'm hunting with your GDB
> > collected data), but could you give me a recipe to cause such a
> > tooltip in the xterm frame by some key-press?
> 
> Sure, you set a breakpoint to some function which gets invoked as 'emacsclient
> -t' starts, like update_frame_line, but forgot to add 'cont' to the list of
> commands. And then you forgot that you didn't add 'cont' and starts
> 'emacsclient -t' and start typing (like some arrow key) without noticing that
> 'emacsclient' frame has yet to appear on the screen. Now look at gdb window,
> breakpoint must have it, do 'cont' there so that emacsclient starts, and now
> you'll see some characters in buffer, with "End of buffer" message in
> minibuffer (tooltip).

But the text I saw was different: it was the text of a tooltip for
mouse-sensitive portions of the mode line:

 Major mode, mouse-1: Display major mode menu, mouse-2: Show help for major mode

Strange.  Anyway, you can forget this for now; if this is important,
we'll get back to it later.

> FTR, I'm still running r111924 for this debugging to avoid adding more
> variables.

OK, that's good.

> > Once you are set up in GDB, make Emacs flicker, and collect the data
> > printed by GDB.  The goal of these breakpoints is to see which code is
> > involved in the flickering situation, and which parts of it are
> > actually writing to the screen.
> 
> The output is attached

Thanks.  Here's what flickering looks like:

  Breakpoint 4, update_frame_line (f=0x12efd88, vpos=0) at dispnew.c:4845
  4845		  write_glyphs (f, nbody, nlen);
  $36808 = 0
  $36809 = 239
  $36810 = 239

  Breakpoint 6, update_frame_line (f=0x12efd88, vpos=0) at dispnew.c:4859
  4859		cursor_to (f, vpos, 0);
  $36811 = 0

  Breakpoint 4, update_frame_line (f=0x12efd88, vpos=1) at dispnew.c:4845
  4845		  write_glyphs (f, nbody, nlen);
  $36812 = 1
  $36813 = 239
  $36814 = 239

  Breakpoint 6, update_frame_line (f=0x12efd88, vpos=1) at dispnew.c:4859
  4859		cursor_to (f, vpos, 0);
  $36815 = 1

  Breakpoint 4, update_frame_line (f=0x12efd88, vpos=2) at dispnew.c:4845
  4845		  write_glyphs (f, nbody, nlen);
  $36816 = 2
  $36817 = 239
  $36818 = 239

  Breakpoint 6, update_frame_line (f=0x12efd88, vpos=2) at dispnew.c:4859
  4859		cursor_to (f, vpos, 0);
  $36819 = 2

  Breakpoint 4, update_frame_line (f=0x12efd88, vpos=3) at dispnew.c:4845
  4845		  write_glyphs (f, nbody, nlen);
  $36820 = 3
  $36821 = 239
  $36822 = 239

  Breakpoint 6, update_frame_line (f=0x12efd88, vpos=3) at dispnew.c:4859
  4859		cursor_to (f, vpos, 0);
  $36823 = 3

  Breakpoint 5, update_frame_line (f=0x12efd88, vpos=4) at dispnew.c:4854
  4854	          clear_end_of_line (f, FRAME_TOTAL_COLS (f));
  $36824 = 4
  $36825 = 239
  $36826 = 0

  Breakpoint 4, update_frame_line (f=0x12efd88, vpos=5) at dispnew.c:4845
  4845		  write_glyphs (f, nbody, nlen);
  $36827 = 5
  $36828 = 239
  $36829 = 27

  Breakpoint 5, update_frame_line (f=0x12efd88, vpos=5) at dispnew.c:4854
  4854	          clear_end_of_line (f, FRAME_TOTAL_COLS (f));
  $36830 = 5
  $36831 = 239
  $36832 = 27

  Breakpoint 5, update_frame_line (f=0x12efd88, vpos=6) at dispnew.c:4854
  4854	          clear_end_of_line (f, FRAME_TOTAL_COLS (f));
  $36833 = 6
  $36834 = 239
  $36835 = 0

  Breakpoint 5, update_frame_line (f=0x12efd88, vpos=7) at dispnew.c:4854
  4854	          clear_end_of_line (f, FRAME_TOTAL_COLS (f));
  $36836 = 7
  $36837 = 239
  $36838 = 0

  Breakpoint 5, update_frame_line (f=0x12efd88, vpos=8) at dispnew.c:4854
  4854	          clear_end_of_line (f, FRAME_TOTAL_COLS (f));
  $36839 = 8
  $36840 = 239
  $36841 = 0

etc., for all the lines of the TTY frame (note the vpos values going
from 0 to 43, for 43-line frame).  For each line on that frame, Emacs
first writes the characters, if any, of the text on that line, and
then clears to the end of the line.

This code is here:


  /* If display line has unknown contents, write the whole line.  */
  if (must_write_whole_line_p)
    {
      [...]
      /* Write the contents of the desired line.  */
      if (nlen)
	{
          cursor_to (f, vpos, 0);
	  write_glyphs (f, nbody, nlen);
	}

      /* Don't call clear_end_of_line if we already wrote the whole
	 line.  The cursor will not be at the right margin in that
	 case but in the line below.  */
      if (nlen < FRAME_TOTAL_COLS (f))
	{
	  cursor_to (f, vpos, nlen);
          clear_end_of_line (f, FRAME_TOTAL_COLS (f));
	}
      else

and must_write_whole_line_p is computed like this:

  /* Current row not enabled means it has unknown contents.  We must
     write the whole desired line in that case.  */
  must_write_whole_line_p = !current_row->enabled_p;

IOW, the problem that causes continuous redrawing of the entire frame
is that every single line ("glyph row") of that frame is marked as
"not enabled" (i.e., invalid) in the current glyph matrix, which is a
structure that describes what is currently on the glass.

The current matrix has every one of its lines marked as valid at the
end of each redisplay cycle.  So the question now is: which code
resets those enabled_p flags of every glyph row in the current matrix,
and thus defeats the code that avoids redrawing the same contents?

To answer that, let's put a watchpoint at the enabled_p flag of one of
the glyph rows.  Like this:

 (gdb) break dispnew.c:2623 if vpos == 5

This breakpoint is inside the make_current function:

  static void
  make_current (struct glyph_matrix *desired_matrix, struct glyph_matrix *current_matrix, int row)
  {
    struct glyph_row *current_row = MATRIX_ROW (current_matrix, row);
    struct glyph_row *desired_row = MATRIX_ROW (desired_matrix, row);
    bool mouse_face_p = current_row->mouse_face_p;

    /* Do current_row = desired_row.  This exchanges glyph pointers
       between both rows, and does a structure assignment otherwise.  */
    assign_row (current_row, desired_row);

    /* Enable current_row to mark it as valid.  */
    current_row->enabled_p = 1;
    current_row->mouse_face_p = mouse_face_p;  <<<<<<<<<<<<<<<<<<<<<<

The choice of the line (5) is arbitrary.  Then wait until the
breakpoint breaks, and do this:

 (gdb) p current_row
 $1 = (struct glyph_row *) 0x37e1158

(The address will be different in your case.)  Now use that address to
put a hardware watchpoint on the enabled_p flag of that glyph row, and
continue the program:

 (gdb) watch ((struct glyph_row *) 0x37e1158)->enabled_p
 (gdb) c

Now do whatever it takes to cause the flicker, and wait for the
watchpoint to trigger, it should say something like

 Hardware watchpoint 5: ((struct glyph_row *) 0x37e1158)->enabled_p

 Old value = 1
 New value = 0

and will next show the source line which modified the value.  Then
type

 (gdb) bt

and let it continue

 (gdb) c

Do this several times, each time waiting until the watchpoint
triggers, and displaying the backtrace.  That should point towards the
code which resets these flags and causes excessive re-drawing.

Thanks.





  reply	other threads:[~2013-03-24 19:54 UTC|newest]

Thread overview: 26+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-03-03 19:19 bug#13864: 24.3.50; emacsclient -t loops when connected to emacs server running in X11 Ashish SHUKLA
2013-03-04 17:50 ` Eli Zaretskii
2013-03-04 19:13   ` Ashish SHUKLA
2013-03-04 20:22     ` Eli Zaretskii
2013-03-05  0:26       ` Ashish SHUKLA
2013-03-06 17:07         ` Eli Zaretskii
2013-03-06 18:52           ` Ashish SHUKLA
2013-03-06 21:00             ` Eli Zaretskii
2013-03-07  1:43               ` Ashish SHUKLA
2013-03-07  6:55                 ` Eli Zaretskii
2013-03-07  7:38                   ` Ashish SHUKLA
2013-03-07  9:16                     ` Eli Zaretskii
2013-03-07 10:19                       ` Ashish SHUKLA
2013-03-07 12:48                         ` Eli Zaretskii
2013-03-08 10:08                           ` Ashish SHUKLA
2013-03-08 15:58                             ` Eli Zaretskii
2013-03-13  9:00                               ` Ashish SHUKLA
2013-03-15  9:39                                 ` Eli Zaretskii
2013-03-22 12:44                                   ` Ashish SHUKLA
2013-03-24 19:54                                     ` Eli Zaretskii [this message]
2013-03-25  9:28                                       ` Ashish SHUKLA
2013-03-25 10:56                                         ` Eli Zaretskii
2013-04-01 16:45                                           ` Ashish SHUKLA
2013-04-02 17:10                                             ` Eli Zaretskii
2013-04-10  9:06                                               ` Ashish SHUKLA
2013-04-10 15:41                                                 ` Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=83k3ow376r.fsf@gnu.org \
    --to=eliz@gnu.org \
    --cc=13864@debbugs.gnu.org \
    --cc=ashish.is@lostca.se \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this external index

	https://git.savannah.gnu.org/cgit/emacs.git
	https://git.savannah.gnu.org/cgit/emacs/org-mode.git

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.