Patch 8.0.0702

254 views
Skip to first unread message

Bram Moolenaar

unread,
Jul 8, 2017, 4:38:36 PM7/8/17
to vim...@googlegroups.com

Patch 8.0.0702
Problem: An error in a timer can make Vim unusable.
Solution: Don't set the error flag or exception from a timer. Stop a timer
if it causes an error 3 out of 3 times. Discard an exception
caused inside a timer.
Files: src/ex_cmds2.c, src/structs.h, src/testdir/test_timers.vim,
runtime/doc/eval.txt


*** ../vim-8.0.0701/src/ex_cmds2.c 2017-07-07 14:50:40.919158114 +0200
--- src/ex_cmds2.c 2017-07-08 22:25:28.836619866 +0200
***************
*** 1197,1207 ****
long current_id = last_timer_id;
# ifdef WIN3264
LARGE_INTEGER fr;

! /* Don't run any timers while exiting. */
! if (exiting)
return next_due;

QueryPerformanceFrequency(&fr);
# endif
profile_start(&now);
--- 1197,1209 ----
long current_id = last_timer_id;
# ifdef WIN3264
LARGE_INTEGER fr;
+ # endif

! /* Don't run any timers while exiting or dealing with an error. */
! if (exiting || aborting())
return next_due;

+ # ifdef WIN3264
QueryPerformanceFrequency(&fr);
# endif
profile_start(&now);
***************
*** 1216,1224 ****
--- 1218,1230 ----
{
int save_timer_busy = timer_busy;
int save_vgetc_busy = vgetc_busy;
+ int did_emsg_save = did_emsg;
+ int called_emsg_save = called_emsg;
+ int did_throw_save = did_throw;

timer_busy = timer_busy > 0 || vgetc_busy > 0;
vgetc_busy = 0;
+ called_emsg = FALSE;
timer->tr_firing = TRUE;
timer_callback(timer);
timer->tr_firing = FALSE;
***************
*** 1226,1235 ****
did_one = TRUE;
timer_busy = save_timer_busy;
vgetc_busy = save_vgetc_busy;

/* Only fire the timer again if it repeats and stop_timer() wasn't
* called while inside the callback (tr_id == -1). */
! if (timer->tr_repeat != 0 && timer->tr_id != -1)
{
profile_setlimit(timer->tr_interval, &timer->tr_due);
this_due = GET_TIMEDIFF(timer, now);
--- 1232,1250 ----
did_one = TRUE;
timer_busy = save_timer_busy;
vgetc_busy = save_vgetc_busy;
+ if (called_emsg)
+ {
+ ++timer->tr_emsg_count;
+ if (!did_throw_save && current_exception != NULL)
+ discard_current_exception();
+ }
+ did_emsg = did_emsg_save;
+ called_emsg = called_emsg_save;

/* Only fire the timer again if it repeats and stop_timer() wasn't
* called while inside the callback (tr_id == -1). */
! if (timer->tr_repeat != 0 && timer->tr_id != -1
! && timer->tr_emsg_count < 3)
{
profile_setlimit(timer->tr_interval, &timer->tr_due);
this_due = GET_TIMEDIFF(timer, now);
*** ../vim-8.0.0701/src/structs.h 2017-07-07 11:53:29.507876589 +0200
--- src/structs.h 2017-07-08 17:24:30.875940359 +0200
***************
*** 3243,3248 ****
--- 3243,3249 ----
long tr_interval; /* msec */
char_u *tr_callback; /* allocated */
partial_T *tr_partial;
+ int tr_emsg_count;
#endif
};

*** ../vim-8.0.0701/src/testdir/test_timers.vim 2017-06-24 16:03:02.751998272 +0200
--- src/testdir/test_timers.vim 2017-07-08 17:53:08.022644231 +0200
***************
*** 189,192 ****
--- 189,210 ----
call assert_equal('hello', g:val)
endfunc

+ func FuncWithError(timer)
+ let g:call_count += 1
+ if g:call_count == 4
+ return
+ endif
+ doesnotexist
+ endfunc
+
+ func Test_timer_errors()
+ let g:call_count = 0
+ let timer = timer_start(10, 'FuncWithError', {'repeat': -1})
+ " Timer will be stopped after failing 3 out of 3 times.
+ call WaitFor('g:call_count == 3')
+ sleep 50m
+ call assert_equal(3, g:call_count)
+ endfunc
+
+
" vim: shiftwidth=2 sts=2 expandtab
*** ../vim-8.0.0701/runtime/doc/eval.txt 2017-06-28 21:26:24.122302194 +0200
--- runtime/doc/eval.txt 2017-07-08 22:33:53.324688990 +0200
***************
*** 8009,8014 ****
--- 8017,8026 ----
"repeat" Number of times to repeat calling the
callback. -1 means forever. When not present
the callback will be called once.
+ If the timer causes an error three times in a
+ row the repeat is cancelled. This avoids that
+ Vim becomes unusable because of all the error
+ messages.

Example: >
func MyHandler(timer)
*** ../vim-8.0.0701/src/version.c 2017-07-08 17:03:15.373760938 +0200
--- src/version.c 2017-07-08 22:31:58.817580630 +0200
***************
*** 766,767 ****
--- 766,769 ----
{ /* Add new patch number below this line */
+ /**/
+ 702,
/**/

--
hundred-and-one symptoms of being an internet addict:
128. You can access the Net -- via your portable and cellular phone.

/// Bram Moolenaar -- Br...@Moolenaar.net -- http://www.Moolenaar.net \\\
/// sponsor Vim, vote for features -- http://www.Vim.org/sponsor/ \\\
\\\ an exciting new programming language -- http://www.Zimbu.org ///
\\\ help me help AIDS victims -- http://ICCF-Holland.org ///

Aron Griffis

unread,
Jul 9, 2017, 11:30:04 AM7/9/17
to vim_dev
On Saturday, July 8, 2017 at 4:38:36 PM UTC-4, Bram Moolenaar wrote:
> Patch 8.0.0702
> Problem: An error in a timer can make Vim unusable.
> Solution: Don't set the error flag or exception from a timer. Stop a timer
> if it causes an error 3 out of 3 times. Discard an exception
> caused inside a timer.
> Files: src/ex_cmds2.c, src/structs.h, src/testdir/test_timers.vim,
> runtime/doc/eval.txt

This patch is causing segfaults for me. I've built with and without it to verify.

I have a timer to check a couple files and update my color scheme when they change. I haven't tried to narrow down any specific lines yet, but when TryTheme actually triggers then vim segfaults immediately. Maybe because of the try/catch?

Here's the code from my vimrc:

function! TryTheme(theme, ...)
let l:background = a:0 ? a:1 : ''
if a:theme == 'solarized'
" force dark bg to prevent double toggle with term scheme
let l:background = 'dark'
endif
if exists('g:colors_name') && g:colors_name == a:theme &&
\ empty(l:background) || &background == l:background
return 1
endif
try
exec 'colorscheme' a:theme
catch /^Vim\%((\a\+)\)\=:E185/
return 0
endtry
if ! empty(l:background)
let &background = l:background
endif
if exists('syntax_on')
syn reset
endif
endfunction

function! LoadTheme()
let l:background_file = expand('~/.vim/background')
let l:theme_file = expand('~/.vim/theme')
let l:background = filereadable(l:background_file) ?
\ readfile(l:background_file)[0] : &background
let l:theme = filereadable(l:theme_file) ?
\ readfile(l:theme_file)[0] : 'default'
if l:background == &background &&
\ exists('g:colors_name') && l:theme == g:colors_name
return 0
endif
" echom l:theme . " " . l:background
call TryTheme(l:theme, l:background)
endfunction

call LoadTheme()

if has("timers")
function! LoadThemeTimer(timer)
call LoadTheme()
endfunction
let theme_timer = timer_start(1000, 'LoadThemeTimer', {'repeat': -1})
endif

Bram Moolenaar

unread,
Jul 9, 2017, 1:19:57 PM7/9/17
to vim...@googlegroups.com, Aron Griffis

Aron Griffis wrote:

> On Saturday, July 8, 2017 at 4:38:36 PM UTC-4, Bram Moolenaar wrote:
> > Patch 8.0.0702
> > Problem: An error in a timer can make Vim unusable.
> > Solution: Don't set the error flag or exception from a timer. Stop a timer
> > if it causes an error 3 out of 3 times. Discard an exception
> > caused inside a timer.
> > Files: src/ex_cmds2.c, src/structs.h, src/testdir/test_timers.vim,
> > runtime/doc/eval.txt
>
> This patch is causing segfaults for me. I've built with and without it to verify.
>
> I have a timer to check a couple files and update my color scheme when they change. I haven't tried to narrow down any specific lines yet, but when TryTheme actually triggers then vim segfaults immediately. Maybe because of the try/catch?
>
> Here's the code from my vimrc:

[..]

I haven't managed to reproduce it. Can you run Vim in a debugger and
see the call stack?

--
hundred-and-one symptoms of being an internet addict:
133. You communicate with people on other continents more than you
do with your own neighbors.

Dominique Pellé

unread,
Jul 9, 2017, 2:29:33 PM7/9/17
to vim_dev
Bram Moolenaar <Br...@moolenaar.net> wrote:

> Aron Griffis wrote:
>
>> On Saturday, July 8, 2017 at 4:38:36 PM UTC-4, Bram Moolenaar wrote:
>> > Patch 8.0.0702
>> > Problem: An error in a timer can make Vim unusable.
>> > Solution: Don't set the error flag or exception from a timer. Stop a timer
>> > if it causes an error 3 out of 3 times. Discard an exception
>> > caused inside a timer.
>> > Files: src/ex_cmds2.c, src/structs.h, src/testdir/test_timers.vim,
>> > runtime/doc/eval.txt
>>
>> This patch is causing segfaults for me. I've built with and without it to verify.
>>
>> I have a timer to check a couple files and update my color scheme when they change. I haven't tried to narrow down any specific lines yet, but when TryTheme actually triggers then vim segfaults immediately. Maybe because of the try/catch?
>>
>> Here's the code from my vimrc:
>
> [..]
>
> I haven't managed to reproduce it. Can you run Vim in a debugger and
> see the call stack?

I could not reproduce it either so far using vim-8.0.704. But I see that
the script sent by the bug reporter contains things like
let l:background_file = expand('~/.vim/background')
and I don't have such a file ~/.vim/background. So it looks
like there are missing instructions to be able to reproduce the
crash.

Regards
Dominique

Christian Brabandt

unread,
Jul 9, 2017, 2:49:36 PM7/9/17
to vim_dev
Yeah, I created those files (put a colorscheme into ~/.vim/themes and a
background setting into ~/.vim/background, be sure, to have something
different than your usual settings and preferably, use a colorscheme
that does not exist) and I now see this segfault:

(gdb) bt
#0 __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:51
#1 0x00007ffff426a3fa in __GI_abort () at abort.c:89
#2 0x00007ffff42a6bd0 in __libc_message (do_abort=do_abort@entry=2, fmt=fmt@entry=0x7ffff439bdd0 "*** Error in `%s': %s: 0x%s ***\n") at ../sysdeps/posix/libc_fatal.c:175
#3 0x00007ffff42acf96 in malloc_printerr (action=3, str=0x7ffff439bf28 "double free or corruption (fasttop)", ptr=<optimized out>, ar_ptr=<optimized out>) at malloc.c:5049
#4 0x00007ffff42ad7de in _int_free (av=0x7ffff45cfb00 <main_arena>, p=0x555555a920e0, have_lock=0) at malloc.c:3905
#5 0x000055555566eeb5 in vim_free (x=0x555555a920f0) at misc2.c:1793
#6 0x0000555555608700 in discard_exception (excp=0x555555ad6ed0, was_finished=0) at ex_eval.c:630
#7 0x0000555555608756 in discard_current_exception () at ex_eval.c:643
#8 0x00005555555ec4f3 in check_due_timer () at ex_cmds2.c:1239
#9 0x00005555556b61c7 in WaitForChar (msec=4000, interrupted=0x7fffffffdc90) at os_unix.c:5500
#10 0x00005555556b1125 in mch_inchar (buf=0x555555a65b14 <typebuf_init+84> "", maxlen=60, wtime=-1, tb_change_cnt=121) at os_unix.c:481
#11 0x0000555555750220 in ui_inchar (buf=0x555555a65b14 <typebuf_init+84> "", maxlen=60, wtime=-1, tb_change_cnt=121) at ui.c:195
#12 0x0000555555635b04 in inchar (buf=0x555555a65b14 <typebuf_init+84> "", maxlen=180, wait_time=-1, tb_change_cnt=121) at getchar.c:3065
#13 0x0000555555635730 in vgetorpeek (advance=1) at getchar.c:2841
#14 0x00005555556338ae in vgetc () at getchar.c:1608
#15 0x0000555555633de3 in safe_vgetc () at getchar.c:1804
#16 0x000055555567ff15 in normal_cmd (oap=0x7fffffffe060, toplevel=1) at normal.c:628
#17 0x00005555557c482c in main_loop (cmdwin=0, noexmode=0) at main.c:1355
#18 0x00005555557c3f96 in vim_main2 () at main.c:908
#19 0x00005555557c3627 in main (argc=5, argv=0x7fffffffe258) at main.c:419


Best,
Christian
--
Wie man sein Kind nicht nennen sollte:
Zita Delle

Aron Griffis

unread,
Jul 9, 2017, 3:06:41 PM7/9/17
to Bram Moolenaar, vim...@googlegroups.com
On Sun, Jul 9, 2017 at 1:19 PM, Bram Moolenaar <Br...@moolenaar.net> wrote:

Aron Griffis wrote:

> On Saturday, July 8, 2017 at 4:38:36 PM UTC-4, Bram Moolenaar wrote:
> > Patch 8.0.0702
> > Problem:    An error in a timer can make Vim unusable.
> > Solution:   Don't set the error flag or exception from a timer.  Stop a timer
> >             if it causes an error 3 out of 3 times.  Discard an exception
> >             caused inside a timer.
> > Files:      src/ex_cmds2.c, src/structs.h, src/testdir/test_timers.vim,
> >             runtime/doc/eval.txt
>
> This patch is causing segfaults for me. I've built with and without it to verify.
>
> I have a timer to check a couple files and update my color scheme when they change. I haven't tried to narrow down any specific lines yet, but when TryTheme actually triggers then vim segfaults immediately. Maybe because of the try/catch?
>
> Here's the code from my vimrc:

[..]

I haven't managed to reproduce it.  Can you run Vim in a debugger and
see the call stack?


Sorry for not including the backtrace earlier. I imagined you'd look at the combination of the 702 patch and my vimrc and the problem would jump out—didn't mean to make extra work for folks trying to repro the segfault.

(gdb) bt
#0  0x00007ffff6af4fd6 in free () from /lib64/libc.so.6
#1  0x0000555555611cc2 in discard_exception (excp=0x555555dec8e0, was_finished=0) at ex_eval.c:633
#2  0x00005555556127e2 in discard_current_exception () at ex_eval.c:643
#3  0x00005555555fa7cb in check_due_timer () at ex_cmds2.c:1239
#4  0x000055555569dd75 in WaitForChar (msec=-1, interrupted=0x7fffffffd8bc) at os_unix.c:5500
#5  0x000055555569de67 in mch_inchar (buf=buf@entry=0x555555a064f9 <typebuf_init+57> "", maxlen=69, wtime=wtime@entry=-1, tb_change_cnt=4) at os_unix.c:481
#6  0x000055555571f40e in ui_inchar (buf=buf@entry=0x555555a064f9 <typebuf_init+57> "", maxlen=maxlen@entry=69, wtime=wtime@entry=-1, tb_change_cnt=tb_change_cnt@entry=4) at ui.c:195
#7  0x00005555556387ea in inchar (buf=0x555555a064f9 <typebuf_init+57> "", maxlen=207, wait_time=-1, tb_change_cnt=4) at getchar.c:3065
#8  0x000055555563a0ed in vgetorpeek (advance=advance@entry=1) at getchar.c:2841
#9  0x000055555563b270 in vgetorpeek (advance=1) at getchar.c:1987
#10 vgetc () at getchar.c:1608                      
#11 0x000055555563b6f9 in safe_vgetc () at getchar.c:1804
#12 0x00005555556812c7 in normal_cmd (oap=0x7fffffffdc00, toplevel=1) at normal.c:628
#13 0x000055555576c875 in main_loop (cmdwin=0, noexmode=0) at main.c:1355
#14 0x000055555576d791 in vim_main2 () at main.c:908
#15 0x00005555555a9491 in main (argc=<optimized out>, argv=<optimized out>) at main.c:419

Full disclosure: My build includes a few extra patches from the Fedora RPM, but since Christian got a similar backtrace, I don't think those patches are related.

Thanks,
Aron

Aron Griffis

unread,
Jul 9, 2017, 3:18:09 PM7/9/17
to Bram Moolenaar, vim...@googlegroups.com
On Sun, Jul 9, 2017 at 3:06 PM, Aron Griffis <agri...@gmail.com> wrote:
On Sun, Jul 9, 2017 at 1:19 PM, Bram Moolenaar <Br...@moolenaar.net> wrote:

Aron Griffis wrote:

> On Saturday, July 8, 2017 at 4:38:36 PM UTC-4, Bram Moolenaar wrote:
> > Patch 8.0.0702
> > Problem:    An error in a timer can make Vim unusable.
> > Solution:   Don't set the error flag or exception from a timer.  Stop a timer
> >             if it causes an error 3 out of 3 times.  Discard an exception
> >             caused inside a timer.
> > Files:      src/ex_cmds2.c, src/structs.h, src/testdir/test_timers.vim,
> >             runtime/doc/eval.txt
>
> This patch is causing segfaults for me. I've built with and without it to verify.
>
> I have a timer to check a couple files and update my color scheme when they change. I haven't tried to narrow down any specific lines yet, but when TryTheme actually triggers then vim segfaults immediately. Maybe because of the try/catch?
>
> Here's the code from my vimrc:

[..]

I haven't managed to reproduce it.  Can you run Vim in a debugger and
see the call stack?


[..]

Full disclosure: My build includes a few extra patches from the Fedora RPM, but since Christian got a similar backtrace, I don't think those patches are related.

In fact, I just rebuilt from pristine 702 source to make sure:

$ CFLAGS=-ggdb ./configure --enable-gui=no --without-x
$ make
$ cd src
$ gdb ./vim
(gdb) run

(change the content of .vim/background and .vim/scheme, cause segfault)

(gdb) bt
#0  0x00007ffff6d0c8f3 in malloc_consolidate.part () from /lib64/libc.so.6
#1  0x00007ffff6d108a6 in _int_malloc () from /lib64/libc.so.6
#2  0x00007ffff6d13a08 in malloc () from /lib64/libc.so.6
#3  0x00000000004dac95 in lalloc (size=2120, message=1) at misc2.c:942
#4  0x00000000004dab62 in alloc (size=2120) at misc2.c:840
#5  0x00000000005b9c1a in call_user_func (fp=0x96db40, argcount=1, argvars=0x7fffffffaa60, rettv=0x7fffffffb180, firstline=1, lastline=1, selfdict=0x0) at userfunc.c:723
#6  0x00000000005bb2ec in call_func (funcname=0x9f9cb0 "airline#statusline(1)", len=18, rettv=0x7fffffffb180, argcount_in=1, argvars_in=0x7fffffffaa60, argv_func=0x0, firstline=1, lastline=1,
    doesrange=0x7fffffffac44, evaluate=1, partial=0x0, selfdict_in=0x0) at userfunc.c:1427
#7  0x00000000005b9560 in get_func_tv (name=0x9f9cb0 "airline#statusline(1)", len=18, rettv=0x7fffffffb180, arg=0x7fffffffb0d0, firstline=1, lastline=1, doesrange=0x7fffffffac44, evaluate=1, partial=0x0,
    selfdict=0x0) at userfunc.c:455
#8  0x0000000000430db4 in eval7 (arg=0x7fffffffb0d0, rettv=0x7fffffffb180, evaluate=1, want_string=0) at eval.c:4332
#9  0x000000000043059c in eval6 (arg=0x7fffffffb0d0, rettv=0x7fffffffb180, evaluate=1, want_string=0) at eval.c:3969
#10 0x0000000000430153 in eval5 (arg=0x7fffffffb0d0, rettv=0x7fffffffb180, evaluate=1) at eval.c:3785
#11 0x000000000042f6b1 in eval4 (arg=0x7fffffffb0d0, rettv=0x7fffffffb180, evaluate=1) at eval.c:3484
#12 0x000000000042f507 in eval3 (arg=0x7fffffffb0d0, rettv=0x7fffffffb180, evaluate=1) at eval.c:3401
#13 0x000000000042f380 in eval2 (arg=0x7fffffffb0d0, rettv=0x7fffffffb180, evaluate=1) at eval.c:3333
#14 0x000000000042f1b7 in eval1 (arg=0x7fffffffb0d0, rettv=0x7fffffffb180, evaluate=1) at eval.c:3261
#15 0x000000000042f110 in eval0 (arg=0x9f2302 "airline#statusline(1)", rettv=0x7fffffffb180, nextcmd=0x0, evaluate=1) at eval.c:3221
#16 0x000000000042a5d6 in eval_to_string (arg=0x9f2302 "airline#statusline(1)", nextcmd=0x0, convert=0) at eval.c:757
#17 0x000000000042a751 in eval_to_string_safe (arg=0x9f2302 "airline#statusline(1)", nextcmd=0x0, use_sandbox=0) at eval.c:805
#18 0x000000000040af55 in build_stl_str_hl (wp=0x87b9d0, out=0x7fffffffc650 "@\336\377\377\377\177", outlen=4096, fmt=0x9f2300 "%!airline#statusline(1)", use_sandbox=0, fillchar=32, maxwidth=213,
    hltab=0x7fffffffc150, tabtab=0x7fffffffbc50) at buffer.c:3893
#19 0x000000000055dc31 in win_redr_custom (wp=0x87b9d0, draw_ruler=0) at screen.c:7161
#20 0x000000000055d6db in redraw_custom_statusline (wp=0x87b9d0) at screen.c:6944
#21 0x000000000055d1b6 in win_redr_status (wp=0x87b9d0) at screen.c:6815
#22 0x000000000055164a in update_screen (type_arg=5) at screen.c:773
#23 0x0000000000550f99 in redraw_after_callback () at screen.c:468
#24 0x000000000045f7b2 in check_due_timer () at ex_cmds2.c:1268
#25 0x000000000051c86e in WaitForChar (msec=-1, interrupted=0x7fffffffd880) at os_unix.c:5500
#26 0x0000000000518718 in mch_inchar (buf=0x86d3fa <typebuf_init+58> "", maxlen=68, wtime=-1, tb_change_cnt=5) at os_unix.c:481
#27 0x00000000005b0d6f in ui_inchar (buf=0x86d3fa <typebuf_init+58> "", maxlen=68, wtime=-1, tb_change_cnt=5) at ui.c:195
#28 0x00000000004a6305 in inchar (buf=0x86d3fa <typebuf_init+58> "", maxlen=206, wait_time=-1, tb_change_cnt=5) at getchar.c:3065
#29 0x00000000004a5fa2 in vgetorpeek (advance=1) at getchar.c:2841
#30 0x00000000004a437c in vgetc () at getchar.c:1608
#31 0x00000000004a4810 in safe_vgetc () at getchar.c:1804
#32 0x00000000004eac40 in normal_cmd (oap=0x7fffffffdc50, toplevel=1) at normal.c:628
#33 0x00000000005e2391 in main_loop (cmdwin=0, noexmode=0) at main.c:1355
#34 0x00000000005e1c48 in vim_main2 () at main.c:908
#35 0x00000000005e143f in main (argc=1, argv=0x7fffffffde48) at main.c:419

Aron Griffis

unread,
Jul 9, 2017, 3:22:40 PM7/9/17
to Bram Moolenaar, vim...@googlegroups.com
On Sun, Jul 9, 2017 at 3:17 PM, Aron Griffis <agri...@gmail.com> wrote:
In fact, I just rebuilt from pristine 702 source to make sure:

$ CFLAGS=-ggdb ./configure --enable-gui=no --without-x
$ make
$ cd src
$ gdb ./vim
(gdb) run

(change the content of .vim/background and .vim/scheme, cause segfault)

I'm not sure why that last backtrace was so long. I just ran again and got a shorter one:

(gdb) bt
#0  0x00007ffff6cbd64b in raise () from /lib64/libc.so.6
#1  0x00007ffff6cbf450 in abort () from /lib64/libc.so.6
#2  0x00007ffff6d03921 in __libc_message () from /lib64/libc.so.6
#3  0x00007ffff6d0e7a9 in _int_free () from /lib64/libc.so.6
#4  0x00007ffff6d1410e in free () from /lib64/libc.so.6
#5  0x00000000004dba25 in vim_free (x=0x9fce50) at misc2.c:1793
#6  0x000000000047a7b2 in discard_exception (excp=0x9fce50, was_finished=0) at ex_eval.c:634
#7  0x000000000047a7d1 in discard_current_exception () at ex_eval.c:643
#8  0x000000000045f66a in check_due_timer () at ex_cmds2.c:1239
#9  0x000000000051c86e in WaitForChar (msec=2000, interrupted=0x7fffffffd870) at os_unix.c:5500
#10 0x0000000000518718 in mch_inchar (buf=0x86d3fa <typebuf_init+58> "", maxlen=68, wtime=-1, tb_change_cnt=5) at os_unix.c:481
#11 0x00000000005b0d6f in ui_inchar (buf=0x86d3fa <typebuf_init+58> "", maxlen=68, wtime=-1, tb_change_cnt=5) at ui.c:195
#12 0x00000000004a6305 in inchar (buf=0x86d3fa <typebuf_init+58> "", maxlen=206, wait_time=-1, tb_change_cnt=5) at getchar.c:3065
#13 0x00000000004a5fa2 in vgetorpeek (advance=1) at getchar.c:2841
#14 0x00000000004a437c in vgetc () at getchar.c:1608
#15 0x00000000004a4810 in safe_vgetc () at getchar.c:1804
#16 0x00000000004eac40 in normal_cmd (oap=0x7fffffffdc40, toplevel=1) at normal.c:628
#17 0x00000000005e2391 in main_loop (cmdwin=0, noexmode=0) at main.c:1355
#18 0x00000000005e1c48 in vim_main2 () at main.c:908
#19 0x00000000005e143f in main (argc=1, argv=0x7fffffffde38) at main.c:419

Dominique Pellé

unread,
Jul 9, 2017, 3:24:59 PM7/9/17
to vim_dev
Can you reproduce the crash with valgrind? It may give
useful information. Just run vim as:

$ valgrind --num-callers=50 --track-origins=yes ./vim 2> vg.log

and vg.log will contain useful info if you manage to reproduce the bug.

Thanks
Dominique

Aron Griffis

unread,
Jul 9, 2017, 3:47:43 PM7/9/17
to vim...@googlegroups.com
On Sun, Jul 9, 2017 at 3:24 PM, Dominique Pellé <dominiq...@gmail.com> wrote:
Can you reproduce the crash with valgrind? It may give
useful information. Just run vim as:

$ valgrind --num-callers=50 --track-origins=yes ./vim 2> vg.log

and vg.log will contain useful info if you manage to reproduce the bug.

Running under valgrind seems to prevent the segfault from happening. 

Christian Brabandt

unread,
Jul 9, 2017, 3:55:35 PM7/9/17
to vim...@googlegroups.com
I get the attached log.

Best,
Christian
--
Windows ist kein Virus - ein Virus tut etwas.
valgrind.log.gz

Ozaki Kiichi

unread,
Jul 10, 2017, 2:47:54 AM7/10/17
to vim_dev
Simply reproducable sample:

test.vim

```
try
throw 'excp'
catch
"
endtry

fu! TimerFunc(...)
echoerr 'oops'
endfu

call timer_start(1, 'TimerFunc')
```

vim -Nu test.vim

cause:

At finishing above try-catch-endtry, "current_exception" has directed a
dangling pointer (already freed).
Therefore, after emsg() is called in timer-callback, "current_exception" is
double-freed.
(at discard_current_exception() in check_due_timer(), ex_cmds2.c:L1239)

details:

* ex_throw() -> throw_exception() sets current_exception (ex_eval.c:L575)
* ex_catch() sets did_throw to FALSE
* ex_endtry() -> cleanup_conditionals() -> finish_exception() -> discard_exception() frees cstack->cs_exception[idx] (== current_exception)
* but, did_throw is already FALSE, discard_current_exception() is not called from anyone (except check_due_timer()).
* thus current_exception is not cleanup and keeps freed pointer.


Ozaki Kiichi

Bram Moolenaar

unread,
Jul 10, 2017, 4:08:39 PM7/10/17
to vim...@googlegroups.com, Ozaki Kiichi
Thanks, that helps a lot to check what happens and verify the fix.

It doesn't work in a test, since those are run inside a try/catch.

The solution is to check whether did_throw is set. I will also clear
current_exception in places where it should no longer be used.

--
Never eat yellow snow.
Reply all
Reply to author
Forward
0 new messages