mirror of
https://github.com/vim/vim.git
synced 2025-09-25 03:54:15 -04:00
patch 8.0.1067: try/catch in timer does not prevent it from being stopped
Problem: Using try/catch in timer does not prevent it from being stopped. Solution: Reset the exception context and use did_emsg instead of called_emsg.
This commit is contained in:
@@ -1219,30 +1219,40 @@ check_due_timer(void)
|
||||
{
|
||||
int save_timer_busy = timer_busy;
|
||||
int save_vgetc_busy = vgetc_busy;
|
||||
int did_emsg_save = did_emsg;
|
||||
int called_emsg_save = called_emsg;
|
||||
int did_throw_save = did_throw;
|
||||
int save_did_emsg = did_emsg;
|
||||
int save_called_emsg = called_emsg;
|
||||
int save_must_redraw = must_redraw;
|
||||
int save_trylevel = trylevel;
|
||||
int save_did_throw = did_throw;
|
||||
except_T *save_current_exception = current_exception;
|
||||
|
||||
/* Create a scope for running the timer callback, ignoring most of
|
||||
* the current scope, such as being inside a try/catch. */
|
||||
timer_busy = timer_busy > 0 || vgetc_busy > 0;
|
||||
vgetc_busy = 0;
|
||||
called_emsg = FALSE;
|
||||
did_emsg = FALSE;
|
||||
did_uncaught_emsg = FALSE;
|
||||
must_redraw = 0;
|
||||
trylevel = 0;
|
||||
did_throw = FALSE;
|
||||
current_exception = NULL;
|
||||
|
||||
timer->tr_firing = TRUE;
|
||||
timer_callback(timer);
|
||||
timer->tr_firing = FALSE;
|
||||
|
||||
timer_next = timer->tr_next;
|
||||
did_one = TRUE;
|
||||
timer_busy = save_timer_busy;
|
||||
vgetc_busy = save_vgetc_busy;
|
||||
if (called_emsg)
|
||||
{
|
||||
if (did_uncaught_emsg)
|
||||
++timer->tr_emsg_count;
|
||||
if (!did_throw_save && did_throw && current_exception != NULL)
|
||||
discard_current_exception();
|
||||
}
|
||||
did_emsg = did_emsg_save;
|
||||
called_emsg = called_emsg_save;
|
||||
did_emsg = save_did_emsg;
|
||||
called_emsg = save_called_emsg;
|
||||
trylevel = save_trylevel;
|
||||
did_throw = save_did_throw;
|
||||
current_exception = save_current_exception;
|
||||
if (must_redraw != 0)
|
||||
need_update_screen = TRUE;
|
||||
must_redraw = must_redraw > save_must_redraw
|
||||
|
@@ -182,6 +182,10 @@ EXTERN dict_T globvardict; /* Dictionary with g: variables */
|
||||
#endif
|
||||
EXTERN int did_emsg; /* set by emsg() when the message
|
||||
is displayed or thrown */
|
||||
#ifdef FEAT_EVAL
|
||||
EXTERN int did_uncaught_emsg; /* emsg() was called and did not
|
||||
cause an exception */
|
||||
#endif
|
||||
EXTERN int did_emsg_syntax; /* did_emsg set because of a
|
||||
syntax error */
|
||||
EXTERN int called_emsg; /* always set by emsg() */
|
||||
|
@@ -609,11 +609,9 @@ emsg(char_u *s)
|
||||
|
||||
called_emsg = TRUE;
|
||||
|
||||
/*
|
||||
* If "emsg_severe" is TRUE: When an error exception is to be thrown,
|
||||
* prefer this message over previous messages for the same command.
|
||||
*/
|
||||
#ifdef FEAT_EVAL
|
||||
/* If "emsg_severe" is TRUE: When an error exception is to be thrown,
|
||||
* prefer this message over previous messages for the same command. */
|
||||
severe = emsg_severe;
|
||||
emsg_severe = FALSE;
|
||||
#endif
|
||||
@@ -684,6 +682,9 @@ emsg(char_u *s)
|
||||
else
|
||||
flush_buffers(FALSE); /* flush internal buffers */
|
||||
did_emsg = TRUE; /* flag for DoOneCmd() */
|
||||
#ifdef FEAT_EVAL
|
||||
did_uncaught_emsg = TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
emsg_on_display = TRUE; /* remember there is an error message */
|
||||
|
@@ -208,6 +208,24 @@ func Test_timer_errors()
|
||||
call assert_equal(3, g:call_count)
|
||||
endfunc
|
||||
|
||||
func FuncWithCaughtError(timer)
|
||||
let g:call_count += 1
|
||||
try
|
||||
doesnotexist
|
||||
catch
|
||||
" nop
|
||||
endtry
|
||||
endfunc
|
||||
|
||||
func Test_timer_catch_error()
|
||||
let g:call_count = 0
|
||||
let timer = timer_start(10, 'FuncWithCaughtError', {'repeat': 4})
|
||||
" Timer will not be stopped.
|
||||
call WaitFor('g:call_count == 4')
|
||||
sleep 50m
|
||||
call assert_equal(4, g:call_count)
|
||||
endfunc
|
||||
|
||||
func FeedAndPeek(timer)
|
||||
call test_feedinput('a')
|
||||
call getchar(1)
|
||||
|
@@ -769,6 +769,8 @@ static char *(features[]) =
|
||||
|
||||
static int included_patches[] =
|
||||
{ /* Add new patch number below this line */
|
||||
/**/
|
||||
1067,
|
||||
/**/
|
||||
1066,
|
||||
/**/
|
||||
|
Reference in New Issue
Block a user