mirror of
https://github.com/neovim/neovim.git
synced 2025-10-17 15:21:47 +00:00
vim-patch:8.0.0702: error in a timer can make Vim unusable #9826
Problem: An error in a timer can make Vim unusable.
Solution: Don't set the error flag or exception from a timer. Stop a timer
if it causes an error 3 out of 3 times. Discard an exception
caused inside a timer.
c577d813b7
closes #9826
This commit is contained in:
@@ -449,6 +449,7 @@ typedef struct {
|
||||
int timer_id;
|
||||
int repeat_count;
|
||||
int refcount;
|
||||
int emsg_count; ///< Errors in a repeating timer.
|
||||
long timeout;
|
||||
bool stopped;
|
||||
bool paused;
|
||||
@@ -17160,6 +17161,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
timer->refcount = 1;
|
||||
timer->stopped = false;
|
||||
timer->paused = false;
|
||||
timer->emsg_count = 0;
|
||||
timer->repeat_count = repeat;
|
||||
timer->timeout = timeout;
|
||||
timer->timer_id = last_timer_id++;
|
||||
@@ -17202,6 +17204,9 @@ static void f_timer_stopall(typval_T *argvars, typval_T *unused, FunPtr fptr)
|
||||
static void timer_due_cb(TimeWatcher *tw, void *data)
|
||||
{
|
||||
timer_T *timer = (timer_T *)data;
|
||||
int save_did_emsg = did_emsg;
|
||||
int save_called_emsg = called_emsg;
|
||||
|
||||
if (timer->stopped || timer->paused) {
|
||||
return;
|
||||
}
|
||||
@@ -17216,8 +17221,24 @@ static void timer_due_cb(TimeWatcher *tw, void *data)
|
||||
argv[0].v_type = VAR_NUMBER;
|
||||
argv[0].vval.v_number = timer->timer_id;
|
||||
typval_T rettv = TV_INITIAL_VALUE;
|
||||
called_emsg = false;
|
||||
|
||||
callback_call(&timer->callback, 1, argv, &rettv);
|
||||
|
||||
// Handle error message
|
||||
if (called_emsg && did_emsg) {
|
||||
timer->emsg_count++;
|
||||
if (current_exception != NULL) {
|
||||
discard_current_exception();
|
||||
}
|
||||
}
|
||||
did_emsg = save_did_emsg;
|
||||
called_emsg = save_called_emsg;
|
||||
|
||||
if (timer->emsg_count >= 3) {
|
||||
timer_stop(timer);
|
||||
}
|
||||
|
||||
tv_clear(&rettv);
|
||||
|
||||
if (!timer->stopped && timer->timeout == 0) {
|
||||
|
Reference in New Issue
Block a user