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.

Regards
-- Dominique

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

Raspunde prin e-mail lui