1
0
forked from aniani/vim

patch 7.4.2312

Problem:    Crash when autocommand moves to another tab. (Dominique Pelle)
Solution:   When navigating to another window halfway the :edit command go
            back to the right window.
This commit is contained in:
Bram Moolenaar
2016-09-03 16:29:04 +02:00
parent dd905a2ae1
commit 5a49789a9b
8 changed files with 59 additions and 26 deletions

View File

@@ -666,7 +666,8 @@ buf_clear_file(buf_T *buf)
/* /*
* buf_freeall() - free all things allocated for a buffer that are related to * buf_freeall() - free all things allocated for a buffer that are related to
* the file. flags: * the file. Careful: get here with "curwin" NULL when exiting.
* flags:
* BFA_DEL buffer is going to be deleted * BFA_DEL buffer is going to be deleted
* BFA_WIPE buffer is going to be wiped out * BFA_WIPE buffer is going to be wiped out
* BFA_KEEP_UNDO do not free undo information * BFA_KEEP_UNDO do not free undo information
@@ -677,7 +678,13 @@ buf_freeall(buf_T *buf, int flags)
#ifdef FEAT_AUTOCMD #ifdef FEAT_AUTOCMD
int is_curbuf = (buf == curbuf); int is_curbuf = (buf == curbuf);
bufref_T bufref; bufref_T bufref;
# ifdef FEAT_WINDOWS
int is_curwin = (curwin!= NULL && curwin->w_buffer == buf);
win_T *the_curwin = curwin;
tabpage_T *the_curtab = curtab;
# endif
/* Make sure the buffer isn't closed by autocommands. */
buf->b_closing = TRUE; buf->b_closing = TRUE;
set_bufref(&bufref, buf); set_bufref(&bufref, buf);
if (buf->b_ml.ml_mfp != NULL) if (buf->b_ml.ml_mfp != NULL)
@@ -705,6 +712,19 @@ buf_freeall(buf_T *buf, int flags)
return; return;
} }
buf->b_closing = FALSE; buf->b_closing = FALSE;
# ifdef FEAT_WINDOWS
/* If the buffer was in curwin and the window has changed, go back to that
* window, if it still exists. This avoids that ":edit x" triggering a
* "tabnext" BufUnload autocmd leaves a window behind without a buffer. */
if (is_curwin && curwin != the_curwin && win_valid_any_tab(the_curwin))
{
block_autocmds();
goto_tabpage_win(the_curtab, the_curwin);
unblock_autocmds();
}
# endif
# ifdef FEAT_EVAL # ifdef FEAT_EVAL
if (aborting()) /* autocmds may abort script processing */ if (aborting()) /* autocmds may abort script processing */
return; return;

View File

@@ -3935,25 +3935,28 @@ do_ecmd(
auto_buf = TRUE; auto_buf = TRUE;
else else
{ {
win_T *the_curwin = curwin;
/* Set the w_closing flag to avoid that autocommands close the
* window. */
the_curwin->w_closing = TRUE;
if (curbuf == old_curbuf.br_buf) if (curbuf == old_curbuf.br_buf)
#endif #endif
buf_copy_options(buf, BCO_ENTER); buf_copy_options(buf, BCO_ENTER);
/* close the link to the current buffer */ /* Close the link to the current buffer. This will set
* curwin->w_buffer to NULL. */
u_sync(FALSE); u_sync(FALSE);
close_buffer(oldwin, curbuf, close_buffer(oldwin, curbuf,
(flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD, FALSE); (flags & ECMD_HIDE) ? 0 : DOBUF_UNLOAD, FALSE);
#ifdef FEAT_AUTOCMD #ifdef FEAT_AUTOCMD
/* Autocommands may open a new window and leave oldwin open the_curwin->w_closing = FALSE;
* which leads to crashes since the above call sets
* oldwin->w_buffer to NULL. */
if (curwin != oldwin && oldwin != aucmd_win
&& win_valid(oldwin) && oldwin->w_buffer == NULL)
win_close(oldwin, FALSE);
# ifdef FEAT_EVAL # ifdef FEAT_EVAL
if (aborting()) /* autocmds may abort script processing */ /* autocmds may abort script processing */
if (aborting() && curwin->w_buffer != NULL)
{ {
vim_free(new_name); vim_free(new_name);
goto theend; goto theend;

View File

@@ -2475,12 +2475,7 @@ do_one_cmd(
&& !IS_USER_CMDIDX(ea.cmdidx)) && !IS_USER_CMDIDX(ea.cmdidx))
{ {
/* Command not allowed when editing the command line. */ /* Command not allowed when editing the command line. */
#ifdef FEAT_CMDWIN errormsg = get_text_locked_msg();
if (cmdwin_type != 0)
errormsg = (char_u *)_(e_cmdwin);
else
#endif
errormsg = (char_u *)_(e_secure);
goto doend; goto doend;
} }
#ifdef FEAT_AUTOCMD #ifdef FEAT_AUTOCMD

View File

@@ -2132,13 +2132,18 @@ text_locked(void)
*/ */
void void
text_locked_msg(void) text_locked_msg(void)
{
EMSG(_(get_text_locked_msg()));
}
char_u *
get_text_locked_msg(void)
{ {
#ifdef FEAT_CMDWIN #ifdef FEAT_CMDWIN
if (cmdwin_type != 0) if (cmdwin_type != 0)
EMSG(_(e_cmdwin)); return e_cmdwin;
else
#endif #endif
EMSG(_(e_secure)); return e_secure;
} }
#if defined(FEAT_AUTOCMD) || defined(PROTO) #if defined(FEAT_AUTOCMD) || defined(PROTO)

View File

@@ -3,6 +3,7 @@ char_u *getcmdline(int firstc, long count, int indent);
char_u *getcmdline_prompt(int firstc, char_u *prompt, int attr, int xp_context, char_u *xp_arg); char_u *getcmdline_prompt(int firstc, char_u *prompt, int attr, int xp_context, char_u *xp_arg);
int text_locked(void); int text_locked(void);
void text_locked_msg(void); void text_locked_msg(void);
char_u *get_text_locked_msg(void);
int curbuf_locked(void); int curbuf_locked(void);
int allbuf_locked(void); int allbuf_locked(void);
char_u *getexline(int c, void *cookie, int indent); char_u *getexline(int c, void *cookie, int indent);

View File

@@ -218,7 +218,7 @@ function Test_tabpage_with_tab_modifier()
bw! bw!
endfunction endfunction
func Test_tabnext_on_buf_unload() func Test_tabnext_on_buf_unload1()
" This once caused a crash " This once caused a crash
new new
tabedit tabedit
@@ -227,7 +227,19 @@ func Test_tabnext_on_buf_unload()
q q
while tabpagenr('$') > 1 while tabpagenr('$') > 1
quit bwipe!
endwhile
endfunc
func Test_tabnext_on_buf_unload2()
" This once caused a crash
tabedit
autocmd BufUnload <buffer> tabnext
file x
edit y
while tabpagenr('$') > 1
bwipe!
endwhile endwhile
endfunc endfunc

View File

@@ -763,6 +763,8 @@ static char *(features[]) =
static int included_patches[] = static int included_patches[] =
{ /* Add new patch number below this line */ { /* Add new patch number below this line */
/**/
2312,
/**/ /**/
2311, 2311,
/**/ /**/

View File

@@ -3912,12 +3912,7 @@ goto_tabpage(int n)
if (text_locked()) if (text_locked())
{ {
/* Not allowed when editing the command line. */ /* Not allowed when editing the command line. */
#ifdef FEAT_CMDWIN text_locked_msg();
if (cmdwin_type != 0)
EMSG(_(e_cmdwin));
else
#endif
EMSG(_(e_secure));
return; return;
} }