Mercurial > vim
changeset 9153:c2fe86f2bda1 v7.4.1860
commit https://github.com/vim/vim/commit/e3188e261569ae512fb1ae2653b57fdd9e259ca3
Author: Bram Moolenaar <Bram@vim.org>
Date: Tue May 31 21:13:04 2016 +0200
patch 7.4.1860
Problem: Using a partial for timer_start() may cause a crash.
Solution: Set the copyID in timer objects. (Ozaki Kiichi)
author | Christian Brabandt <cb@256bit.org> |
---|---|
date | Tue, 31 May 2016 21:15:06 +0200 |
parents | b780d4eac8c7 |
children | da5cc3ccf479 |
files | src/eval.c src/ex_cmds2.c src/proto/ex_cmds2.pro src/testdir/test_timers.vim src/version.c |
diffstat | 5 files changed, 36 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- 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) { /*
--- 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)
--- a/src/proto/ex_cmds2.pro +++ b/src/proto/ex_cmds2.pro @@ -22,6 +22,7 @@ timer_T *create_timer(long msec, int rep 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);
--- 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