Dominique Pelle wrote:

> Once in a while, I see that Vim enters an endless loop and takes 100% of
> the CPU.  I've seen this bug a couple times when using the Perforce plugin:
> I try to edit file, the perforce plugin asks to checkout the file, I enter 
> 'Y',
> the file gets checked-out but then Vim sometimes loops forever using
> 100% of the CPU!?
> 
> It does not happens all the time and it's quite rare.  I don't have
> a reproducible test case, which makes it hard to debug. It just
> happened today using Vim-7.2.163 (in xterm on Linux x86_64).
> I attached to the runaway process with cgcb and I can see where
> it's looping forever:
> 
> edit.c:
> 
> 6433         for (;;)
> 6434         {
> 6435†>           if (gchar_cursor() == NUL && curwin->w_cursor.col > 0)
> 6436                 --curwin->w_cursor.col;
> 6437             cc = gchar_cursor();
> 6438             if (!vim_iswhite(cc))
> 6439                 break;
> 6440             (void)del_char(TRUE);
> 6441         }
> 
> Stepping over line by line with gdb, the following lines in edit.c
> are being executed indefinitely:
> 
>   6435, 6437, 6438, 6440 and then back to
>   6435, 6437, 6438, 6440, etc.
> 
> While looping, I see that 'curwin->w_cursor' and 'cc' always remained
> identical:
> 
>   (gdb) p curwin->w_cursor
>   $11 = {
>     lnum = 133,
>     col = 2,
>     coladd = 0
>   }
> 
>   (gdb) p cc
>   $12 = 32
> 
> The file I was editing has 1487 lines.  Line 133 is an empty line.
> So the column of the cursor (2) looks wrong I think.
> 
> When stepping into del_char(TRUE) at line 6440, I see that del_bytes()
> always returns FAIL at misc1.c:2213:
> 
> #0  del_bytes (count=1, fixpos_arg=1, use_delcombine=1) at misc1.c:2213
> #1  0x00000000004cd622 in del_chars (count=1, fixpos=1) at misc1.c:2180
> #2  0x00000000004cd58c in del_char (fixpos=1) at misc1.c:2153
> #3  0x000000000042a7c9 in stop_insert (end_insert_pos=0x83b870, esc=1)
> at edit.c:6440
> #4  0x000000000042c968 in ins_esc (count=0x7fff8c049c68, cmdchar=65,
> nomove=0) at edit.c:7954
> #5  0x0000000000421a86 in edit (cmdchar=65, startln=0, count=-1) at edit.c:927
> #6  0x00000000004f66f4 in invoke_edit (cap=0x7fff8c049db0, repl=0,
> cmd=65, startln=0) at normal.c:8888
> #7  0x00000000004f6691 in nv_edit (cap=0x7fff8c049db0) at normal.c:8861
> #8  0x00000000004e946d in normal_cmd (oap=0x7fff8c049e80, toplevel=1)
> at normal.c:1189
> #9  0x00000000004a90a2 in main_loop (cmdwin=0, noexmode=0) at main.c:1180
> #10 0x00000000004a8be8 in main (argc=2, argv=0x7fff8c04a178) at main.c:939
> 
> 
> 2193  del_bytes(count, fixpos_arg, use_delcombine)
> 2194      long        count;
> 2195      int         fixpos_arg;
> 2196      int         use_delcombine;     /* 'delcombine' option applies */
> 2197  {
> 2198      char_u      *oldp, *newp;
> 2199      colnr_T     oldlen;
> 2200      linenr_T    lnum = curwin->w_cursor.lnum;
> 2201      colnr_T     col = curwin->w_cursor.col;
> 2202      int         was_alloced;
> 2203      long        movelen;
> 2204      int         fixpos = fixpos_arg;
> 2205 
> 2206      oldp = ml_get(lnum);
> 2207      oldlen = (int)STRLEN(oldp);
> 2208 
> 2209      /*
> 2210       * Can't do anything when the cursor is on the NUL after the line.
> 2211       */
> 2212      if (col >= oldlen)
> 2213†>        return FAIL;
> 
>   (gdb) p col
>   $34 = 2
>   (gdb) p oldlen
>   $35 = 0
> 
>   (gdb) p oldp
>   $36 = (char_u *) 0x8f59a7 ""
>   (gdb) p lnum
>   $37 = 133
> 
> I also see the following thing which is probably wrong in this stack trace:
> 
> (gdb) bt
> #0  ml_get_buf (buf=0x83d0b0, lnum=133, will_change=0) at memline.c:2143
> #1  0x00000000004ba367 in ml_get_cursor () at memline.c:2064
> #2  0x00000000004cdaac in gchar_cursor () at misc1.c:2394
> #3  0x000000000042a789 in stop_insert (end_insert_pos=0x83b870, esc=1)
> at edit.c:6435
> #4  0x000000000042c968 in ins_esc (count=0x7fff8c049c68, cmdchar=65,
> nomove=0) at edit.c:7954
> #5  0x0000000000421a86 in edit (cmdchar=65, startln=0, count=-1) at edit.c:927
> #6  0x00000000004f66f4 in invoke_edit (cap=0x7fff8c049db0, repl=0,
> cmd=65, startln=0) at normal.c:8888
> #7  0x00000000004f6691 in nv_edit (cap=0x7fff8c049db0) at normal.c:8861
> #8  0x00000000004e946d in normal_cmd (oap=0x7fff8c049e80, toplevel=1)
> at normal.c:1189
> #9  0x00000000004a90a2 in main_loop (cmdwin=0, noexmode=0) at main.c:1180
> #10 0x00000000004a8be8 in main (argc=2, argv=0x7fff8c04a178) at main.c:939
> 
> 2058  /*
> 2059   * ml_get_cursor: get pointer to cursor position
> 2060   */
> 2061      char_u *
> 2062  ml_get_cursor()
> 2063  {
> 2064      return (ml_get_buf(curbuf, curwin->w_cursor.lnum, FALSE) +
> 2065 
> curwin->w_cursor.col);
> 2066†>}
> 
> At line 2064, ml_get_buf(...) returns an empty string "" (consistent
> with the fact that my file has an empty line at line 133) but
> curwin->w_cursor.col
> is 2 which looks wrong.  Adding 2 to the empty string goes beyond the
> end of string.
> So it seems that curwin->w_cursor.col is incorrect.
> 
> ml_get_cursor() ends up returning 32 in this case:
> 
>   (gdb) p buf->b_ml.ml_line_ptr
>   $49 = (char_u *) 0x8f59a7 ""
> 
>   (gdb) p ((char_u *) 0x8f59a7)[2]
>   $50 = 32 ' '
> 
> Since getchar_cursor() at edit.c:6435 returns 32, lines edit.c:6436 is
> never executed so curwin->w_cursor.col is never decremented and remains 2
> all the time.
> 
> I suspect that code should check the return code of del_char(TRUE)
> at edit.c:6440 and break from the loop if it fails to avoid
> an infinite loop.  But I think that would only be working around
> the real bug: curwin->w_cursor.col being incorrect.
> 
> Since I don't know how to systematically reproduce this bug, it's
> hard to experiment to see how to fix it.  Hopefully the above
> information might be enough to figure it out.  Sorry, no patch for
> this yet.

We can use the return value of del_char() to break the loop.  But I
wonder how the cursor ever ended up pointing beyond the end of the line.
I suppose some auto-indenting was done, which the loop is supposed to
remove.  Either something happened in between the auto-indenting and
setting end_insert_pos, or there never was any auto-indenting.

-- 
ARTHUR: Listen, old crone!  Unless you tell us where we can buy a shrubbery,
        my friend and I will ... we will say "Ni!"
CRONE:  Do your worst!
                 "Monty Python and the Holy Grail" PYTHON (MONTY) PICTURES LTD

 /// Bram Moolenaar -- [email protected] -- http://www.Moolenaar.net   \\\
///        sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\        download, build and distribute -- http://www.A-A-P.org        ///
 \\\            help me help AIDS victims -- http://ICCF-Holland.org    ///

--~--~---------~--~----~------------~-------~--~----~
You received this message from the "vim_dev" maillist.
For more information, visit http://www.vim.org/maillist.php
-~----------~----~----~----~------~----~------~--~---

Raspunde prin e-mail lui