aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorBjörn Linse <bjorn.linse@gmail.com>2016-08-10 11:46:38 +0200
committerGitHub <noreply@github.com>2016-08-10 11:46:38 +0200
commitadd41dca98b748a84a022c828bc47e0e47e58332 (patch)
tree55107929dd62fcfdb163284170a37034f8b33157 /src
parentdb375102ead998421a180525299f66db3e6127f3 (diff)
parent0a51d26b33d3d540a380563049bbd8fe610bd12f (diff)
downloadrneovim-add41dca98b748a84a022c828bc47e0e47e58332.tar.gz
rneovim-add41dca98b748a84a022c828bc47e0e47e58332.tar.bz2
rneovim-add41dca98b748a84a022c828bc47e0e47e58332.zip
Merge pull request #5192 from bfredl/closetime
timer: do not crash when processing events in the handler
Diffstat (limited to 'src')
-rw-r--r--src/nvim/eval.c17
1 files changed, 14 insertions, 3 deletions
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 7839a7f645..38aa587d37 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -435,6 +435,7 @@ typedef struct {
TimeWatcher tw;
int timer_id;
int repeat_count;
+ int refcount;
long timeout;
bool stopped;
ufunc_T *callback;
@@ -16775,6 +16776,7 @@ static void f_timer_start(typval_T *argvars, typval_T *rettv)
func->uf_refcount++;
timer = xmalloc(sizeof *timer);
+ timer->refcount = 1;
timer->stopped = false;
timer->repeat_count = repeat;
timer->timeout = timeout;
@@ -16817,6 +16819,7 @@ static void timer_due_cb(TimeWatcher *tw, void *data)
if (timer->stopped) {
return;
}
+ timer->refcount++;
// if repeat was negative repeat forever
if (timer->repeat_count >= 0 && --timer->repeat_count == 0) {
timer_stop(timer);
@@ -16840,6 +16843,7 @@ static void timer_due_cb(TimeWatcher *tw, void *data)
// when the main loop is blocked.
time_watcher_start(&timer->tw, timer_due_cb, 0, 0);
}
+ timer_decref(timer);
}
static void timer_stop(timer_T *timer)
@@ -16850,17 +16854,24 @@ static void timer_stop(timer_T *timer)
}
timer->stopped = true;
time_watcher_stop(&timer->tw);
- time_watcher_close(&timer->tw, timer_free_cb);
+ time_watcher_close(&timer->tw, timer_close_cb);
}
// invoked on next event loop tick, so queue is empty
-static void timer_free_cb(TimeWatcher *tw, void *data)
+static void timer_close_cb(TimeWatcher *tw, void *data)
{
timer_T *timer = (timer_T *)data;
queue_free(timer->tw.events);
user_func_unref(timer->callback);
pmap_del(uint64_t)(timers, timer->timer_id);
- xfree(timer);
+ timer_decref(timer);
+}
+
+static void timer_decref(timer_T *timer)
+{
+ if (--timer->refcount == 0) {
+ xfree(timer);
+ }
}
void timer_teardown(void)