]> granicus.if.org Git - vim/commitdiff
patch 7.4.2304 v7.4.2304
authorBram Moolenaar <Bram@vim.org>
Thu, 1 Sep 2016 19:26:20 +0000 (21:26 +0200)
committerBram Moolenaar <Bram@vim.org>
Thu, 1 Sep 2016 19:26:20 +0000 (21:26 +0200)
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.

src/ex_cmds2.c
src/testdir/test_timers.vim
src/version.c

index 85513af296c79c0e8d9b1a4a4be42d74ef9cac6a..a76b055220dfa1ed85c73a32d5d883ba8838989a 100644 (file)
@@ -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;
            }
index 152f72502152bb6a222947e04a4952bd61314f0f..e6e54a4cbdc4ee646149588fa35577fa9d8f0daf 100644 (file)
@@ -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
index edee28a67f31fd8286c447cba7544e541c07e453..b0ee536bdc832915b640e43d4099239e459e492b 100644 (file)
@@ -763,6 +763,8 @@ static char *(features[]) =
 
 static int included_patches[] =
 {   /* Add new patch number below this line */
+/**/
+    2304,
 /**/
     2303,
 /**/