summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-09-01 21:26:20 +0200
committerBram Moolenaar <Bram@vim.org>2016-09-01 21:26:20 +0200
commit417ccd7138d4d230d328de8b0d3892dd82ff1bee (patch)
tree9dbbb0b04dd9a3eba03b1d949348d1616b878aef
parent779f2fc3a7468e273897d2fd0672315812a2e3da (diff)
patch 7.4.2304v7.4.2304
Problem: In a timer callback the timer itself can't be found or stopped. (Thinca) Solution: Do not remove the timer from the list, remember whether it was freed.
-rw-r--r--src/ex_cmds2.c23
-rw-r--r--src/testdir/test_timers.vim15
-rw-r--r--src/version.c2
3 files changed, 35 insertions, 5 deletions
diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c
index 85513af296..a76b055220 100644
--- a/src/ex_cmds2.c
+++ b/src/ex_cmds2.c
@@ -1090,6 +1090,9 @@ profile_zero(proftime_T *tm)
static timer_T *first_timer = NULL;
static int last_timer_id = 0;
+static timer_T *current_timer = NULL;
+static int free_current_timer = FALSE;
+
/*
* Insert a timer in the list of timers.
*/
@@ -1121,8 +1124,13 @@ remove_timer(timer_T *timer)
static void
free_timer(timer_T *timer)
{
- free_callback(timer->tr_callback, timer->tr_partial);
- vim_free(timer);
+ if (timer == current_timer)
+ free_current_timer = TRUE;
+ else
+ {
+ free_callback(timer->tr_callback, timer->tr_partial);
+ vim_free(timer);
+ }
}
/*
@@ -1200,18 +1208,23 @@ check_due_timer(void)
# endif
if (this_due <= 1)
{
- remove_timer(timer);
+ current_timer = timer;
+ free_current_timer = FALSE;
timer_callback(timer);
+ current_timer = NULL;
+
did_one = TRUE;
- if (timer->tr_repeat != 0)
+ if (timer->tr_repeat != 0 && !free_current_timer)
{
profile_setlimit(timer->tr_interval, &timer->tr_due);
if (timer->tr_repeat > 0)
--timer->tr_repeat;
- insert_timer(timer);
}
else
+ {
free_timer(timer);
+ remove_timer(timer);
+ }
/* the callback may do anything, start all over */
break;
}
diff --git a/src/testdir/test_timers.vim b/src/testdir/test_timers.vim
index 152f725021..e6e54a4cbd 100644
--- a/src/testdir/test_timers.vim
+++ b/src/testdir/test_timers.vim
@@ -128,4 +128,19 @@ func Test_paused()
endif
endfunc
+func StopMyself(timer)
+ let g:called += 1
+ if g:called == 2
+ call timer_stop(a:timer)
+ endif
+endfunc
+
+func Test_delete_myself()
+ let g:called = 0
+ let t = timer_start(10, 'StopMyself', {'repeat': -1})
+ call WaitFor('g:called == 2')
+ call assert_equal(2, g:called)
+ call assert_equal([], timer_info(t))
+endfunc
+
" vim: shiftwidth=2 sts=2 expandtab
diff --git a/src/version.c b/src/version.c
index edee28a67f..b0ee536bdc 100644
--- a/src/version.c
+++ b/src/version.c
@@ -764,6 +764,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2304,
+/**/
2303,
/**/
2302,