Problem:
Vim crashes with SEGV or BUS when netbeans is processing a command and
concurrently receives a socket disconnection event. This is difficult
to reproduce as timing is critical. The first two backtraces below
are the result of such a crash. In both cases, examination of the
variables 'node' and 'head', in the netbeans_parse_messages() function
show that their 'next' or 'prev' pointers are invalid.
Description:
The third backtrace is obtained after setting a breakpoint in
nb_free() and this backtrace explains the crashes:
. a netbeans command is processed by netbeans_parse_messages()
. this command triggers an autocommand
. this causes ui_breakcheck() to be called and control is passed
to the gui event loop that in turn calls netbeans_read()
. netbeans_read() receives the disconnection event and calls
netbeans_close()
. netbeans_close() clears all the netbeans data structures, so
that when control returns to netbeans_parse_messages(), this
function is now working on invalidated (probably re-used) memory
Patch:
The attached patch to vim 7.3.047 fixes the problem by queueing the
"DETACH" netbeans message in the command queue when netbeans_read()
processes the socket disconnection. This way, the netbeans data
structures are cleared later by netbeans_parse_messages() in vim idle
loop when processing this "DETACH" command, and not anymore in the gui
event loop (or the select loop).
=======================================================================
1 - Crash in vim_free:
#11 0x00007f83e8624ab6 in free () from /lib/libc.so.6
#12 0x00000000004d443f in vim_free (x=0x18c7e00) at misc2.c:1699
#13 0x00000000005ac178 in netbeans_parse_messages () at netbeans.c:685
#14 0x00000000005a74e6 in gui_mch_wait_for_chars (wtime=3600000) at
gui_gtk_x11.c:5423
#15 0x0000000000597f16 in gui_wait_for_chars (wtime=-1) at gui.c:2718
#16 0x000000000058106a in ui_inchar (buf=0x8286f6 "", maxlen=80,
wtime=-1, tb_change_cnt=23) at ui.c:184
#17 0x0000000000499691 in inchar (buf=0x8286f6 "", maxlen=242,
wait_time=-1, tb_change_cnt=23) at getchar.c:3004
#18 0x00000000004992a0 in vgetorpeek (advance=1) at getchar.c:2780
#19 0x00000000004974ed in vgetc () at getchar.c:1559
#20 0x0000000000497a6d in safe_vgetc () at getchar.c:1764
#21 0x00000000004e40c7 in normal_cmd (oap=0x7fff51af12a0, toplevel=1)
at normal.c:654
#22 0x00000000004a6159 in main_loop (cmdwin=0, noexmode=0) at main.c:1260
#23 0x00000000004a5c39 in main (argc=1, argv=0x7fff51af1598) at main.c:965
=======================================================================
2 - Crash in off2pos:
#7 0x00000000005b1432 in off2pos (buf=0x30303005, offset=0) at netbeans.c:3778
#8 0x00000000005b151c in get_off_or_lnum (buf=0x30303005,
argp=0x7fffb66780b0) at netbeans.c:3813
#9 0x00000000005aeaca in nb_do_cmd (bufno=2, cmd=0x1d934a2 "",
func=0, cmdno=39, args=0x1d934ac "\307\177") at netbeans.c:2234
#10 0x00000000005ac4d5 in nb_parse_cmd (cmd=0x1d934a0 "") at netbeans.c:902
#11 0x00000000005ac161 in netbeans_parse_messages () at netbeans.c:680
#12 0x00000000005a74e6 in gui_mch_wait_for_chars (wtime=3600000) at
gui_gtk_x11.c:5423
#13 0x0000000000597f16 in gui_wait_for_chars (wtime=-1) at gui.c:2718
#14 0x000000000058106a in ui_inchar (buf=0x82871d "", maxlen=67,
wtime=-1, tb_change_cnt=62) at ui.c:184
#15 0x0000000000499691 in inchar (buf=0x82871d "", maxlen=203,
wait_time=-1, tb_change_cnt=62) at getchar.c:3004
#16 0x00000000004992a0 in vgetorpeek (advance=1) at getchar.c:2780
#17 0x00000000004974ed in vgetc () at getchar.c:1559
#18 0x0000000000497a6d in safe_vgetc () at getchar.c:1764
#19 0x00000000004e40c7 in normal_cmd (oap=0x7fffb6678930, toplevel=1)
at normal.c:654
#20 0x00000000004a6159 in main_loop (cmdwin=0, noexmode=0) at main.c:1260
#21 0x00000000004a5c39 in main (argc=1, argv=0x7fffb6678c28) at main.c:965
=======================================================================
3 - Backtrace while vim is stopped at a breakpoint in nb_free()
#0 nb_free () at netbeans.c:955
#1 0x00000000005ab5bc in netbeans_close () at netbeans.c:179
#2 0x00000000005ac320 in netbeans_read () at netbeans.c:796
#3 0x00000000005ac1dd in messageFromNetbeans (clientData=0x0,
unused1=4, unused2=GDK_INPUT_READ) at netbeans.c:719
#4 0x00007fa5e80a6e2f in ?? () from /usr/lib/libgdk-x11-2.0.so.0
#5 0x00007fa5e6eb27ab in g_main_context_dispatch () from
/usr/lib/libglib-2.0.so.0
#6 0x00007fa5e6eb5f7d in ?? () from /usr/lib/libglib-2.0.so.0
#7 0x00007fa5e6eb613b in g_main_context_iteration () from
/usr/lib/libglib-2.0.so.0
#8 0x00000000005a7436 in gui_mch_update () at gui_gtk_x11.c:5331
#9 0x000000000058122e in ui_breakcheck () at ui.c:364
#10 0x00000000004d084c in line_breakcheck () at misc1.c:8518
#11 0x000000000048ece5 in auto_next_pat (apc=0x7fffb4de0360,
stop_at_last=0) at fileio.c:9552
#12 0x000000000048e7d8 in apply_autocmds_group
(event=EVENT_BUFWINLEAVE, fname=0xad5a30
"/home/xavier/src/pyclewn-hg-pdb/foobar.py",
fname_io=0x8890f0 "foobar.py", force=0, group=-3, buf=0x887060,
eap=0x0) at fileio.c:9358
#13 0x000000000048e125 in apply_autocmds (event=EVENT_BUFWINLEAVE,
fname=0x8890f0 "foobar.py", fname_io=0x8890f0 "foobar.py", force=0,
buf=0x887060)
at fileio.c:8994
#14 0x000000000040ede6 in close_buffer (win=0x8857e0, buf=0x887060,
action=0) at buffer.c:372
#15 0x0000000000456ab9 in do_ecmd (fnum=0, ffname=0x9ba120
"/home/xavier/src/pyclewn-hg-pdb/(clewn)_console", sfname=0xaaa680
"(clewn)_console",
eap=0x0, newlnum=1, flags=5, oldwin=0x8857e0) at ex_cmds.c:3398
#16 0x00000000005ae5de in nb_do_cmd (bufno=1, cmd=0xae8fa2
"editFile", func=0, cmdno=11, args=0xae8fae "\"(clewn)_console\"") at
netbeans.c:2074
#17 0x00000000005ac4d5 in nb_parse_cmd (cmd=0xae8fa0 "1:editFile")
at netbeans.c:902
#18 0x00000000005ac161 in netbeans_parse_messages () at netbeans.c:680
#19 0x00000000005a74e6 in gui_mch_wait_for_chars (wtime=3600000) at
gui_gtk_x11.c:5423
#20 0x0000000000597f16 in gui_wait_for_chars (wtime=-1) at gui.c:2718
#21 0x000000000058106a in ui_inchar (buf=0x8286f5 "", maxlen=81,
wtime=-1, tb_change_cnt=22) at ui.c:184
#22 0x0000000000499691 in inchar (buf=0x8286f5 "", maxlen=243,
wait_time=-1, tb_change_cnt=22) at getchar.c:3004
#23 0x00000000004992a0 in vgetorpeek (advance=1) at getchar.c:2780
#24 0x00000000004974ed in vgetc () at getchar.c:1559
#25 0x0000000000497a6d in safe_vgetc () at getchar.c:1764
#26 0x00000000004e40c7 in normal_cmd (oap=0x7fffb4de0e90,
toplevel=1) at normal.c:654
#27 0x00000000004a6159 in main_loop (cmdwin=0, noexmode=0) at main.c:1260
#28 0x00000000004a5c39 in main (argc=1, argv=0x7fffb4de1188) at main.c:965
=======================================================================
--
Xavier
Les Chemins de Lokoti: http://lokoti.alwaysdata.net
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
diff --git a/src/netbeans.c b/src/netbeans.c
--- a/src/netbeans.c
+++ b/src/netbeans.c
@@ -136,13 +136,8 @@
static int inAtomic = 0;
static void
-netbeans_close(void)
+nb_close_socket(void)
{
- if (!NETBEANS_OPEN)
- return;
-
- netbeans_send_disconnect();
-
#ifdef FEAT_GUI_X11
if (inputHandler != (XtInputId)NULL)
{
@@ -167,13 +162,23 @@
# endif
#endif
+ sock_close(nbsock);
+ nbsock = -1;
+}
+
+ static void
+netbeans_close(void)
+{
+ if (NETBEANS_OPEN)
+ {
+ netbeans_send_disconnect();
+ nb_close_socket();
+ }
+
#ifdef FEAT_BEVAL
bevalServers &= ~BEVAL_NETBEANS;
#endif
- sock_close(nbsock);
- nbsock = -1;
-
needupdate = 0;
inAtomic = 0;
nb_free();
@@ -632,9 +637,6 @@
char_u *p;
queue_T *node;
- if (!NETBEANS_OPEN)
- return;
-
while (head.next != NULL && head.next != &head)
{
node = head.next;
@@ -720,6 +722,8 @@
}
#endif
+#define DETACH_MSG "DETACH\n"
+
void
netbeans_read()
{
@@ -790,17 +794,27 @@
break; /* did read everything that's available */
}
+ /* Reading a socket disconnection (readlen == 0), or a socket error. */
if (readlen <= 0)
{
- /* read error or didn't read anything */
- netbeans_close();
- nbdebug(("messageFromNetbeans: Error in read() from socket\n"));
+ /* Queue a "DETACH" netbeans message in the command queue in order to
+ * terminate the netbeans session later. Do not end the session here
+ * directly as we may be running in the context of a call to
+ * netbeans_parse_messages():
+ * netbeans_parse_messages
+ * -> autocmd triggered while processing the netbeans cmd
+ * -> ui_breakcheck
+ * -> gui event loop or select loop
+ * -> netbeans_read()
+ */
+ save((char_u *)DETACH_MSG, strlen(DETACH_MSG));
+ nb_close_socket();
+
if (len < 0)
{
nbdebug(("read from Netbeans socket\n"));
PERROR(_("read from Netbeans socket"));
}
- return; /* don't try to parse it */
}
#if defined(NB_HAS_GUI) && !defined(FEAT_GUI_W32)
@@ -1186,6 +1200,10 @@
nbdebug(("REP %d: <none>\n", cmdno));
+ /* Avoid printing an annoying error message. */
+ if (!NETBEANS_OPEN)
+ return;
+
sprintf(reply, "%d\n", cmdno);
nb_send(reply, "nb_reply_nil");
}