summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBram Moolenaar <Bram@vim.org>2016-08-11 22:51:05 +0200
committerBram Moolenaar <Bram@vim.org>2016-08-11 22:51:05 +0200
commitc257487035f83aabe1c7e07f0552309e98f1bcb1 (patch)
treea2ab08ae7d067a1c5eba06a677f8480c5a166f6b
parent91c5262b19fd2e558fe87b78c7767c7c5a270be8 (diff)
patch 7.4.2197v7.4.2197
Problem: All functions are freed on exit, which may hide leaks. Solution: Only free named functions, not reference counted ones.
-rw-r--r--src/userfunc.c55
-rw-r--r--src/version.c2
2 files changed, 38 insertions, 19 deletions
diff --git a/src/userfunc.c b/src/userfunc.c
index 065425965c..55bd97c5ba 100644
--- a/src/userfunc.c
+++ b/src/userfunc.c
@@ -1099,22 +1099,53 @@ func_free(ufunc_T *fp, int force)
vim_free(fp);
}
+/*
+ * There are two kinds of function names:
+ * 1. ordinary names, function defined with :function
+ * 2. numbered functions and lambdas
+ * For the first we only count the name stored in func_hashtab as a reference,
+ * using function() does not count as a reference, because the function is
+ * looked up by name.
+ */
+ static int
+func_name_refcount(char_u *name)
+{
+ return isdigit(*name) || *name == '<';
+}
+
#if defined(EXITFREE) || defined(PROTO)
void
free_all_functions(void)
{
hashitem_T *hi;
+ ufunc_T *fp;
+ long_u skipped = 0;
+ long_u todo;
/* Need to start all over every time, because func_free() may change the
* hash table. */
- while (func_hashtab.ht_used > 0)
- for (hi = func_hashtab.ht_array; ; ++hi)
+ while (func_hashtab.ht_used > skipped)
+ {
+ todo = func_hashtab.ht_used;
+ for (hi = func_hashtab.ht_array; todo > 0; ++hi)
if (!HASHITEM_EMPTY(hi))
{
- func_free(HI2UF(hi), TRUE);
- break;
+ --todo;
+ /* Only free functions that are not refcounted, those are
+ * supposed to be freed when no longer referenced. */
+ fp = HI2UF(hi);
+ if (func_name_refcount(fp->uf_name))
+ ++skipped;
+ else
+ {
+ func_free(fp, TRUE);
+ skipped = 0;
+ break;
+ }
}
- hash_clear(&func_hashtab);
+ }
+ if (skipped == 0)
+ hash_clear(&func_hashtab);
}
#endif
@@ -1669,20 +1700,6 @@ theend:
}
/*
- * There are two kinds of function names:
- * 1. ordinary names, function defined with :function
- * 2. numbered functions and lambdas
- * For the first we only count the name stored in func_hashtab as a reference,
- * using function() does not count as a reference, because the function is
- * looked up by name.
- */
- static int
-func_name_refcount(char_u *name)
-{
- return isdigit(*name) || *name == '<';
-}
-
-/*
* ":function"
*/
void
diff --git a/src/version.c b/src/version.c
index 85053e1391..5ba3eec7fc 100644
--- a/src/version.c
+++ b/src/version.c
@@ -764,6 +764,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 2197,
+/**/
2196,
/**/
2195,