summaryrefslogtreecommitdiff
path: root/ext/File-Glob/Glob.xs
diff options
context:
space:
mode:
authorFather Chrysostomos <sprout@cpan.org>2012-12-09 06:05:22 -0800
committerFather Chrysostomos <sprout@cpan.org>2012-12-09 18:47:21 -0800
commit11ddfebc6e521f916fd05108e3faa74e7ed132b8 (patch)
tree6b2b9261790150d860d432183c3570ce76ca5ae3 /ext/File-Glob/Glob.xs
parent6e2f1cd4c88b28bee7c3d0d21ce95d5b9fc4f991 (diff)
downloadperl-11ddfebc6e521f916fd05108e3faa74e7ed132b8.tar.gz
Don’t leak when partly iterated glob op is freed
File::Glob keeps its own hash of arrays of file names. Each array corresponds to one call site. When iteration finishes, it deletes the array. But if iteration never finishes, and the op at the call site is freed, the array remains. So eval "scalar<*>" will cause a memory leak. We already have a mechanism for hooking the freeing of ops. So File::Glob can use that.
Diffstat (limited to 'ext/File-Glob/Glob.xs')
-rw-r--r--ext/File-Glob/Glob.xs17
1 files changed, 17 insertions, 0 deletions
diff --git a/ext/File-Glob/Glob.xs b/ext/File-Glob/Glob.xs
index 50bb2daacf..4c08776215 100644
--- a/ext/File-Glob/Glob.xs
+++ b/ext/File-Glob/Glob.xs
@@ -312,6 +312,19 @@ doglob_iter_wrapper(pTHX_ AV *entries, SV *patsv)
return FALSE;
}
+static Perl_ophook_t old_ophook;
+
+static void
+glob_ophook(pTHX_ OP *o)
+{
+ dMY_CXT;
+ if (MY_CXT.x_GLOB_ENTRIES
+ && (o->op_type == OP_GLOB || o->op_type == OP_ENTERSUB))
+ hv_delete(MY_CXT.x_GLOB_ENTRIES, (char *)&o, sizeof(OP *),
+ G_DISCARD);
+ if (old_ophook) old_ophook(aTHX_ o);
+}
+
MODULE = File::Glob PACKAGE = File::Glob
int
@@ -385,6 +398,10 @@ BOOT:
dMY_CXT;
MY_CXT.x_GLOB_ENTRIES = NULL;
}
+ OP_REFCNT_LOCK;
+ old_ophook = PL_opfreehook;
+ PL_opfreehook = glob_ophook;
+ OP_REFCNT_UNLOCK;
}
INCLUDE: const-xs.inc