Hi Alex!
On Do, 24 Mai 2012, Alex Efros wrote:
> I've discover this bug when trying to ':wq' in file with syntax errors using
> syntastic plugin with
> let g:syntastic_auto_loc_list=1
> Instead of exiting from vim no matter there are syntax errors I got either
> E855: Autocommands caused command to abort
> or vim segfault.
>
>
> To reproduce this bug it's enough to:
>
> $ vi -u /dev/null --noplugin
> :autocmd BufWinLeave * if empty(&bt) | lclose | endif
> :lexpr system('echo :1:some')
> :lopen
> :wincmd p
> :q
> (location list closes; got message E855: Autocommands caused command to
> abort; vim doesn't exit)
> :q
> (now vim exit)
I have noticed something similar in my NrrwRgn plugin.
I am not sure, this is a bug, because at the time you issue :q the
location list ist still open and in case another window is open, :q does
not exit Vim.
> Or, with tabs and segfault:
>
> $ vi -u /dev/null --noplugin
> :autocmd BufWinLeave * if empty(&bt) | lclose | endif
> :tabnew
> :lexpr system('echo :1:some')
> :lopen
> :wincmd p
> :q
> Vim: Caught deadly signal SEGV
> Vim: Finished.
> Segmentation fault
>
> This happens on 7.3.515. Versions before 7.3.449 behave differently
> without tabs, but with tabs they all crash.
Attached patch fixes this issue.
regards,
Christian
--
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/proto/window.pro b/src/proto/window.pro
--- a/src/proto/window.pro
+++ b/src/proto/window.pro
@@ -9,6 +9,7 @@
void win_equal __ARGS((win_T *next_curwin, int current, int dir));
void close_windows __ARGS((buf_T *buf, int keep_curwin));
int one_window __ARGS((void));
+int close_last_window_tabpage __ARGS((win_T *win, int free_buf, tabpage_T *prev_curtab));
void win_close __ARGS((win_T *win, int free_buf));
void win_close_othertab __ARGS((win_T *win, int free_buf, tabpage_T *tp));
void win_free_all __ARGS((void));
diff --git a/src/window.c b/src/window.c
--- a/src/window.c
+++ b/src/window.c
@@ -2104,6 +2104,38 @@
#endif
}
+int
+close_last_window_tabpage(win, free_buf, prev_curtab)
+ win_T *win;
+ int free_buf;
+ tabpage_T *prev_curtab;
+{
+ /*
+ * When closing the last window in a tab page first go to another tab
+ * page and then close the window and the tab page. This avoids that
+ * curwin and curtab are not invalid while we are freeing memory, they may
+ * be used in GUI events.
+ */
+ if (firstwin == lastwin)
+ {
+ goto_tabpage_tp(alt_tabpage());
+ redraw_tabline = TRUE;
+
+ /* Safety check: Autocommands may have closed the window when jumping
+ * to the other tab page. */
+ if (valid_tabpage(prev_curtab) && prev_curtab->tp_firstwin == win)
+ {
+ int h = tabline_height();
+
+ win_close_othertab(win, free_buf, prev_curtab);
+ if (h != tabline_height())
+ shell_new_rows();
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
/*
* Close window "win". Only works for the current tab page.
* If "free_buf" is TRUE related buffer may be unloaded.
@@ -2146,26 +2178,11 @@
/*
* When closing the last window in a tab page first go to another tab
* page and then close the window and the tab page. This avoids that
- * curwin and curtab are not invalid while we are freeing memory, they may
+ * curwin and curtab are invalid while we are freeing memory, they may
* be used in GUI events.
*/
- if (firstwin == lastwin)
- {
- goto_tabpage_tp(alt_tabpage());
- redraw_tabline = TRUE;
-
- /* Safety check: Autocommands may have closed the window when jumping
- * to the other tab page. */
- if (valid_tabpage(prev_curtab) && prev_curtab->tp_firstwin == win)
- {
- int h = tabline_height();
-
- win_close_othertab(win, free_buf, prev_curtab);
- if (h != tabline_height())
- shell_new_rows();
- }
- return;
- }
+ if (close_last_window_tabpage(win, free_buf, prev_curtab))
+ return;
/* When closing the help window, try restoring a snapshot after closing
* the window. Otherwise clear the snapshot, it's now invalid. */
@@ -2225,7 +2242,8 @@
/* Autocommands may have closed the window already, or closed the only
* other window or moved to another tab page. */
- if (!win_valid(win) || last_window() || curtab != prev_curtab)
+ if (!win_valid(win) || last_window() || curtab != prev_curtab
+ || close_last_window_tabpage(win, free_buf, prev_curtab))
return;
/* Free the memory used for the window and get the window that received
@@ -2310,7 +2328,7 @@
/*
* Close window "win" in tab page "tp", which is not the current tab page.
- * This may be the last window ih that tab page and result in closing the tab,
+ * This may be the last window in that tab page and result in closing the tab,
* thus "tp" may become invalid!
* Caller must check if buffer is hidden and whether the tabline needs to be
* updated.