diff options
| author | Björn Linse <bjorn.linse@gmail.com> | 2016-08-10 11:46:38 +0200 | 
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-08-10 11:46:38 +0200 | 
| commit | add41dca98b748a84a022c828bc47e0e47e58332 (patch) | |
| tree | 55107929dd62fcfdb163284170a37034f8b33157 /src/nvim/eval.c | |
| parent | db375102ead998421a180525299f66db3e6127f3 (diff) | |
| parent | 0a51d26b33d3d540a380563049bbd8fe610bd12f (diff) | |
| download | rneovim-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/nvim/eval.c')
| -rw-r--r-- | src/nvim/eval.c | 17 | 
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) | 
