diff options
author | Bram Moolenaar <Bram@vim.org> | 2016-05-31 21:13:04 +0200 |
---|---|---|
committer | Bram Moolenaar <Bram@vim.org> | 2016-05-31 21:13:04 +0200 |
commit | e3188e261569ae512fb1ae2653b57fdd9e259ca3 (patch) | |
tree | 87c05229ae16e555ac400824415470337734dba4 | |
parent | ef3abc6442260e9a0314970a532400b05571d3fe (diff) | |
download | vim-git-e3188e261569ae512fb1ae2653b57fdd9e259ca3.tar.gz |
patch 7.4.1860v7.4.1860
Problem: Using a partial for timer_start() may cause a crash.
Solution: Set the copyID in timer objects. (Ozaki Kiichi)
-rw-r--r-- | src/eval.c | 4 | ||||
-rw-r--r-- | src/ex_cmds2.c | 19 | ||||
-rw-r--r-- | src/proto/ex_cmds2.pro | 1 | ||||
-rw-r--r-- | src/testdir/test_timers.vim | 10 | ||||
-rw-r--r-- | src/version.c | 2 |
5 files changed, 36 insertions, 0 deletions
diff --git a/src/eval.c b/src/eval.c index 3578c9997..d30a76653 100644 --- a/src/eval.c +++ b/src/eval.c @@ -7046,6 +7046,10 @@ garbage_collect(int testing) abort = abort || set_ref_in_nb_channel(copyID); #endif +#ifdef FEAT_TIMERS + abort = abort || set_ref_in_timer(copyID); +#endif + if (!abort) { /* diff --git a/src/ex_cmds2.c b/src/ex_cmds2.c index a90fe7d8c..9adaea357 100644 --- a/src/ex_cmds2.c +++ b/src/ex_cmds2.c @@ -1252,6 +1252,25 @@ stop_timer(timer_T *timer) remove_timer(timer); free_timer(timer); } + +/* + * Mark references in partials of timers. + */ + int +set_ref_in_timer(int copyID) +{ + int abort = FALSE; + timer_T *timer; + typval_T tv; + + for (timer = first_timer; timer != NULL; timer = timer->tr_next) + { + tv.v_type = VAR_PARTIAL; + tv.vval.v_partial = timer->tr_partial; + abort = abort || set_ref_in_item(&tv, copyID, NULL, NULL); + } + return abort; +} # endif #if defined(FEAT_SYN_HL) && defined(FEAT_RELTIME) && defined(FEAT_FLOAT) diff --git a/src/proto/ex_cmds2.pro b/src/proto/ex_cmds2.pro index 5e5b4d4b7..8d9b72a24 100644 --- a/src/proto/ex_cmds2.pro +++ b/src/proto/ex_cmds2.pro @@ -22,6 +22,7 @@ timer_T *create_timer(long msec, int repeats); long check_due_timer(void); timer_T *find_timer(int id); void stop_timer(timer_T *timer); +int set_ref_in_timer(int copyID); void profile_divide(proftime_T *tm, int count, proftime_T *tm2); void profile_add(proftime_T *tm, proftime_T *tm2); void profile_self(proftime_T *self, proftime_T *total, proftime_T *children); diff --git a/src/testdir/test_timers.vim b/src/testdir/test_timers.vim index 7ef51e5b5..0969377c8 100644 --- a/src/testdir/test_timers.vim +++ b/src/testdir/test_timers.vim @@ -8,6 +8,10 @@ func MyHandler(timer) let s:val += 1 endfunc +func MyHandlerWithLists(lists, timer) + let x = string(a:lists) +endfunc + func Test_oneshot() let s:val = 0 let timer = timer_start(50, 'MyHandler') @@ -42,4 +46,10 @@ func Test_with_partial_callback() sleep 200m call assert_equal(1, s:val) endfunc + +func Test_retain_partial() + call timer_start(100, function('MyHandlerWithLists', [['a']])) + call test_garbagecollect_now() + sleep 200m +endfunc " vim: ts=2 sw=0 et diff --git a/src/version.c b/src/version.c index eb9f2c711..515f51876 100644 --- a/src/version.c +++ b/src/version.c @@ -754,6 +754,8 @@ static char *(features[]) = static int included_patches[] = { /* Add new patch number below this line */ /**/ + 1860, +/**/ 1859, /**/ 1858, |