The attached patch seems to fix the crash reported here: https://groups.google.com/d/topic/vim_dev/Nr8Ja4Zjghw/discussion
The fix is simple in concept: any recursive call can be replaced with
an explicit stack to "cheat" your way into an iterative algorithm. So
that is what I did. I kept the calling structure unchanged, but pass
an explicit stack around for hash tables and lists. If the stack is
non-null, setting the reference just adds an item to the stack instead
of actually dropping into the HT or list to set its children. Setting
the children of a list or HT will continue processing the stack until
the stack is empty rather than only processing one item.
Sourcing the attached "crashtest.vim" before the patch crashes Vim
every time. After the patch, Vim is busy for nearly a minute, but then
recovers, and does not crash.
Memory use seems to be handled correctly. Looking at the memory column
in Windows Vista's Task Manager, I sourced the script, then did
":unlet dict list" to free up the memory created in the script that
still has a reference. Doing this repeatedly gave me the following
memory use:
After ":unlet" After ":source"
29500 174100
16016 173832
29436 175872
20748 174076
32892 180872
24568 173656
31772 180896
27168 175796
33008 182448
27244 175732
33144 181944
28864 177812
34500 182464
28516 176716
As you can see, Vim's memory footprint seems to fluctuate a little,
possibly due to fragmentation or something, but does not continue
definitely growing. I would appreciate if someone tested with Valgrind
or something to make sure.
There are problems remaining.
First, if I don't use :unlet dict list, but instead source the script
again and allow the previous values to be garbage collected, Vim stays
busy for at least an hour. I don't know if it ever finishes because I
killed the process. I used gdb on MinGW to see that Vim DOES get
through the "set reference" calls in the garbage collector which my
patch fixed; so I expect Vim is busy with the recursive calls to
actually free the garbage-collected memory. These could probably be
fixed in the same way I fixed the reference setting recursion. I think
this deserves a separate patch.
Secondly, the explicit stacks rely on malloc'ing more memory during
garbage collection, to create the stack entries. If this malloc fails,
I have simply abandoned the current garbage collection run without
doing anything. Should this throw a user-visible error? If it happens
too often Vim may run out of memory, it would be good to give the user
an opportunity to save their work and restart Vim gracefully.
Related to this, I wasn't sure whether I needed to reset any of these
values when aborting the garbage collection:
want_garbage_collect = FALSE;
may_garbage_collect = FALSE;
garbage_collect_at_exit = FALSE;
Do any of these need to be set TRUE to allow Vim another try at
garbage collection later?
Finally, setting references in the LUA interface doesn't currently
allow aborting for failure using this patch. I could not figure out,
how to get a return value from lua_call. Can someone familiar with the
LUA interface code please help with this?
--
--
You received this message from the "vim_dev" maillist.
Do not top-post! Type your reply below the text you are replying to.
For more information, visit http://www.vim.org/maillist.php
---
You received this message because you are subscribed to the Google Groups
"vim_dev" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
crashtest.vim
Description: Binary data
iter_GC_set_ref.patch
Description: Binary data
