summaryrefslogtreecommitdiffstats
path: root/src/userfunc.c
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2021-03-17 15:03:04 +0100
committerBram Moolenaar <Bram@vim.org>2021-03-17 15:03:04 +0100
commitc970e4225b68ff8650ff23df09e04246c147fca3 (patch)
tree9c46d37f0a911323058fd11964a69e72aa98d80a /src/userfunc.c
parent6ccfd99b923cc3452a6e6450dfdd7e31ea602dfd (diff)
patch 8.2.2614: Vim9: function is deleted while executingv8.2.2614
Problem: Vim9: function is deleted while executing. Solution: increment the call count, when more than zero do not delete the function but mark it as dead. (closes #7977)
Diffstat (limited to 'src/userfunc.c')
-rw-r--r--src/userfunc.c30
1 files changed, 22 insertions, 8 deletions
diff --git a/src/userfunc.c b/src/userfunc.c
index e89b8858d3..4793ee5552 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1359,9 +1359,12 @@ func_remove(ufunc_T *fp)
// function, so we can find the index when defining the function again.
// Do remove it when it's a copy.
if (fp->uf_def_status == UF_COMPILED && (fp->uf_flags & FC_COPY) == 0)
+ {
fp->uf_flags |= FC_DEAD;
- else
- hash_remove(&func_hashtab, hi);
+ return FALSE;
+ }
+ hash_remove(&func_hashtab, hi);
+ fp->uf_flags |= FC_DELETED;
return TRUE;
}
return FALSE;
@@ -2134,11 +2137,23 @@ delete_script_functions(int sid)
int changed = func_hashtab.ht_changed;
fp->uf_flags |= FC_DEAD;
- func_clear(fp, TRUE);
- // When clearing a function another function can be cleared
- // as a side effect. When that happens start over.
- if (changed != func_hashtab.ht_changed)
- break;
+
+ if (fp->uf_calls > 0)
+ {
+ // Function is executing, don't free it but do remove
+ // it from the hashtable.
+ if (func_remove(fp))
+ fp->uf_refcount--;
+ }
+ else
+ {
+ func_clear(fp, TRUE);
+ // When clearing a function another function can be
+ // cleared as a side effect. When that happens start
+ // over.
+ if (changed != func_hashtab.ht_changed)
+ break;
+ }
}
--todo;
}
@@ -4251,7 +4266,6 @@ ex_delfunction(exarg_T *eap)
// do remove it from the hashtable.
if (func_remove(fp))
fp->uf_refcount--;
- fp->uf_flags |= FC_DELETED;
}
else
func_clear_free(fp, FALSE);