mirror of
https://github.com/neovim/neovim.git
synced 2025-09-13 23:08:16 +00:00
vim-patch:7.4.1727
Problem: Cannot detect a crash in tests when caused by garbagecollect().
Solution: Add garbagecollect_for_testing(). Do not free a job if is still
useful.
ebf7dfa6f1
This commit is contained in:
@@ -389,6 +389,7 @@ static struct vimvar {
|
||||
VV(VV__NULL_LIST, "_null_list", VAR_LIST, VV_RO),
|
||||
VV(VV__NULL_DICT, "_null_dict", VAR_DICT, VV_RO),
|
||||
VV(VV_VIM_DID_ENTER, "vim_did_enter", VAR_NUMBER, VV_RO),
|
||||
VV(VV_TESTING, "testing", VAR_NUMBER, 0),
|
||||
VV(VV_TYPE_NUMBER, "t_number", VAR_NUMBER, VV_RO),
|
||||
VV(VV_TYPE_STRING, "t_string", VAR_NUMBER, VV_RO),
|
||||
VV(VV_TYPE_FUNC, "t_func", VAR_NUMBER, VV_RO),
|
||||
@@ -648,8 +649,8 @@ void eval_clear(void)
|
||||
xfree(SCRIPT_SV(i));
|
||||
ga_clear(&ga_scripts);
|
||||
|
||||
/* unreferenced lists and dicts */
|
||||
(void)garbage_collect();
|
||||
// unreferenced lists and dicts
|
||||
(void)garbage_collect(false);
|
||||
|
||||
/* functions */
|
||||
free_all_functions();
|
||||
@@ -5813,6 +5814,9 @@ int get_copyID(void)
|
||||
return current_copyID;
|
||||
}
|
||||
|
||||
// Used by get_func_tv()
|
||||
static garray_T funcargs = GA_EMPTY_INIT_VALUE;
|
||||
|
||||
/*
|
||||
* Garbage collection for lists and dictionaries.
|
||||
*
|
||||
@@ -5835,16 +5839,19 @@ int get_copyID(void)
|
||||
|
||||
/// Do garbage collection for lists and dicts.
|
||||
///
|
||||
/// @param testing true if called from test_garbagecollect_now().
|
||||
/// @returns true if some memory was freed.
|
||||
bool garbage_collect(void)
|
||||
bool garbage_collect(bool testing)
|
||||
{
|
||||
bool abort = false;
|
||||
#define ABORTING(func) abort = abort || func
|
||||
|
||||
// Only do this once.
|
||||
want_garbage_collect = false;
|
||||
may_garbage_collect = false;
|
||||
garbage_collect_at_exit = false;
|
||||
if (!testing) {
|
||||
// Only do this once.
|
||||
want_garbage_collect = false;
|
||||
may_garbage_collect = false;
|
||||
garbage_collect_at_exit = false;
|
||||
}
|
||||
|
||||
// We advance by two because we add one for items referenced through
|
||||
// previous_funccal.
|
||||
@@ -5954,6 +5961,12 @@ bool garbage_collect(void)
|
||||
})
|
||||
}
|
||||
|
||||
// function call arguments, if v:testing is set.
|
||||
for (int i = 0; i < funcargs.ga_len; i++) {
|
||||
ABORTING(set_ref_in_item)(((typval_T **)funcargs.ga_data)[i],
|
||||
copyID, NULL, NULL);
|
||||
}
|
||||
|
||||
// v: vars
|
||||
ABORTING(set_ref_in_ht)(&vimvarht, copyID, NULL);
|
||||
|
||||
@@ -6008,7 +6021,7 @@ bool garbage_collect(void)
|
||||
if (did_free_funccal) {
|
||||
// When a funccal was freed some more items might be garbage
|
||||
// collected, so run again.
|
||||
(void)garbage_collect();
|
||||
(void)garbage_collect(testing);
|
||||
}
|
||||
} else if (p_verbose > 0) {
|
||||
verb_msg((char_u *)_(
|
||||
@@ -7085,9 +7098,24 @@ get_func_tv (
|
||||
ret = FAIL;
|
||||
|
||||
if (ret == OK) {
|
||||
ret = call_func(name, len, rettv, argcount, argvars,
|
||||
int i = 0;
|
||||
|
||||
if (get_vim_var_nr(VV_TESTING)) {
|
||||
// Prepare for calling garbagecollect_for_testing(), need to know
|
||||
// what variables are used on the call stack.
|
||||
if (funcargs.ga_itemsize == 0) {
|
||||
ga_init(&funcargs, (int)sizeof(typval_T *), 50);
|
||||
}
|
||||
for (i = 0; i < argcount; i++) {
|
||||
ga_grow(&funcargs, 1);
|
||||
((typval_T **)funcargs.ga_data)[funcargs.ga_len++] = &argvars[i];
|
||||
}
|
||||
}
|
||||
ret = call_func(name, len, rettv, argcount, argvars, NULL,
|
||||
firstline, lastline, doesrange, evaluate,
|
||||
partial, selfdict);
|
||||
|
||||
funcargs.ga_len -= i;
|
||||
} else if (!aborting()) {
|
||||
if (argcount == MAX_FUNC_ARGS) {
|
||||
emsg_funcname(N_("E740: Too many arguments for function %s"), name);
|
||||
@@ -17306,6 +17334,14 @@ static void f_termopen(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
return;
|
||||
}
|
||||
|
||||
// "test_garbagecollect_now()" function
|
||||
static void f_test_garbagecollect_now(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||
{
|
||||
// This is dangerous, any Lists and Dicts used internally may be freed
|
||||
// while still in use.
|
||||
garbage_collect(true);
|
||||
}
|
||||
|
||||
static bool callback_from_typval(Callback *callback, typval_T *arg)
|
||||
{
|
||||
if (arg->v_type == VAR_PARTIAL && arg->vval.v_partial != NULL) {
|
||||
|
Reference in New Issue
Block a user