Oh, what a nasty bug!

After having debugged eclim to find out what might trigger this it comes down 
to be reproducible like this:

1. Start vim: vim -u NONE -N --cmd 'call gettabvar(1, "bar") | au BufEnter * 
echom "TRIGGERED"'
2. Remove the initial message, e.g. ":<cr>"
3. Open the cmdline-window: q/

The BufEnter autocommand (and likely WinEnter also) gets triggered, if 
`gettabvar()` has been called with the current tabpagenr().
It does not happen when using "0"or a non-existing tab with gettabvar.

The reason for this is that in `switch_win` in `f_gettabvar` will unblock 
autocommands on failure, although that is what `restore_win` is meant to do.
(code reference: 
https://github.com/vim-jp/vim/blob/master/src/eval.c#L12087-12101)

The attached patch fixes this, according to the doc comment from `switch_win`:
 * restore_win() MUST be called to undo.

It adjusts two other places where the code was returning on switch_win-failure 
only.

Please consider adding tests for this.

This bug appears to exist since 7.3.963 probably 
(https://github.com/vim-jp/vim/commit/b4af40af94851dcd1327c7a65c6da8d72937053d).

There is also a call to `block_autocmds` in `free_all_mem` without a 
corresponding call to `unblock_autocmds`, but that might be expected?! I have 
not checked where this is used.

Patch URL: 
https://github.com/blueyed/vim/compare/fix-switch_win-no-unblock_autocmds.patch


Regards,
Daniel.

Am Samstag, 13. September 2014 19:49:59 UTC+2 schrieb Daniel Hahler:
> It appears that &buftype is not correctly set with the BufEnter autocommand 
> for a cmdline-window.
> 
> I've noticed this with a BufEnter autocommand that checks for &buftype, and 
> the documentation states that it should be "nofile" for the cmdline-window, 
> but it's empty.
> 
> Additionally, according to the documentation, BufEnter shouldn't get 
> triggered at all for a cmdline-window (from cmdline.txt):
> 
> > Two autocommand events are used: |CmdwinEnter| and |CmdwinLeave|.  Since 
> > this
> window is of a special type, the WinEnter, WinLeave, BufEnter and BufLeave
> events are not triggered.
> 
> 
> I've seen a similar oddity before, where &buftype appeared to be not current 
> with a WinEnter autocommand, and in that case it helped to use BufEnter.
> 
> 
> Regards,
> Daniel.

-- 
-- 
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

--- 
You received this message because you are subscribed to the Google Groups 
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to vim_dev+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
>From e17f089f2df1d19ec2d932e284c835b2cbc6c35d Mon Sep 17 00:00:00 2001
From: Daniel Hahler <g...@thequod.de>
Date: Sat, 13 Sep 2014 21:31:56 +0200
Subject: [PATCH 1/2] Do not call unblock_autocmds on failure in switch_win

restore_win is meant to do this!
---
 src/window.c | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/src/window.c b/src/window.c
index 5012427..309de67 100644
--- a/src/window.c
+++ b/src/window.c
@@ -6696,12 +6696,8 @@ switch_win(save_curwin, save_curtab, win, tp, no_display)
 	    goto_tabpage_tp(tp, FALSE, FALSE);
     }
     if (!win_valid(win))
-    {
-# ifdef FEAT_AUTOCMD
-	unblock_autocmds();
-# endif
 	return FAIL;
-    }
+
     curwin = win;
     curbuf = curwin->w_buffer;
 # endif

>From f2193a2d88abbad48ed1c43f2a96d512c489bc51 Mon Sep 17 00:00:00 2001
From: Daniel Hahler <g...@thequod.de>
Date: Sat, 13 Sep 2014 21:56:37 +0200
Subject: [PATCH 2/2] Call `restore_win` on `switch_win` failure in `setwinvar`
 and if_py

This is required after the fix in e17f089.

Also add a question/TODO/note to free_all_mem.
---
 src/eval.c       | 4 +++-
 src/if_py_both.h | 1 +
 src/misc2.c      | 1 +
 3 files changed, 5 insertions(+), 1 deletion(-)

diff --git a/src/eval.c b/src/eval.c
index dfcb586..321a22d 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -17252,8 +17252,10 @@ setwinvar(argvars, rettv, off)
     if (win != NULL && varname != NULL && varp != NULL)
     {
 #ifdef FEAT_WINDOWS
-	if (switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == FAIL)
+	if (switch_win(&save_curwin, &save_curtab, win, tp, TRUE) == FAIL) {
+            restore_win(save_curwin, save_curtab, TRUE);
 	    return;
+        }
 #endif
 
 	if (*varname == '&')
diff --git a/src/if_py_both.h b/src/if_py_both.h
index 5044afb..45c5158 100644
--- a/src/if_py_both.h
+++ b/src/if_py_both.h
@@ -3172,6 +3172,7 @@ set_option_value_for(
 	    if (switch_win(&save_curwin, &save_curtab, (win_T *)from,
 			      win_find_tabpage((win_T *)from), FALSE) == FAIL)
 	    {
+		restore_win(save_curwin, save_curtab, FALSE);
 		if (VimTryEnd())
 		    return -1;
 		PyErr_SET_VIM(N_("problem while switching windows"));
diff --git a/src/misc2.c b/src/misc2.c
index 1f8878f..09b1b78 100644
--- a/src/misc2.c
+++ b/src/misc2.c
@@ -1040,6 +1040,7 @@ free_all_mem()
     entered = TRUE;
 
 # ifdef FEAT_AUTOCMD
+    // NOTE: no call to unblock_autocmds?!
     block_autocmds();	    /* don't want to trigger autocommands here */
 # endif
 

Raspunde prin e-mail lui