From: Vincent Pit Date: Sat, 4 Jul 2009 10:39:19 +0000 (+0200) Subject: Stop leaking the op specific info X-Git-Tag: v0.08~6 X-Git-Url: http://git.vpit.fr/?p=perl%2Fmodules%2FLexical-Types.git;a=commitdiff_plain;h=fbe95a2d759869fa1c790eb26d9dab02a27c8651 Stop leaking the op specific info This needs extra care under multiplicity perls. We can't actually use a SV because there's no way to free it in the context of the interpreter it was allocated from : it may very well not exist anymore at this point. --- diff --git a/MANIFEST b/MANIFEST index f14794d..f8c8cf3 100644 --- a/MANIFEST +++ b/MANIFEST @@ -20,6 +20,7 @@ t/21-tie.t t/22-magic.t t/23-magic-uvar.t t/30-threads.t +t/40-stress.t t/91-pod.t t/92-pod-coverage.t t/95-portability-files.t diff --git a/Types.xs b/Types.xs index f3ce903..a01cc15 100644 --- a/Types.xs +++ b/Types.xs @@ -319,9 +319,14 @@ STATIC perl_mutex lt_op_map_mutex; #endif typedef struct { +#if LT_MULTIPLICITY + STRLEN buf_size, orig_pkg_len, type_pkg_len, type_meth_len; + char *buf; +#else /* LT_MULTIPLICITY */ SV *orig_pkg; SV *type_pkg; SV *type_meth; +#endif /* !LT_MULTIPLICITY */ OP *(*pp_padsv)(pTHX); } lt_op_info; @@ -336,11 +341,45 @@ STATIC void lt_map_store(pPTBLMS_ const OP *o, SV *orig_pkg, SV *type_pkg, SV *t if (!(oi = ptable_fetch(lt_op_map, o))) { oi = PerlMemShared_malloc(sizeof *oi); ptable_map_store(lt_op_map, o, oi); +#if LT_MULTIPLICITY + oi->buf = NULL; + oi->buf_size = 0; +#else /* LT_MULTIPLICITY */ + } else { + SvREFCNT_dec(oi->orig_pkg); + SvREFCNT_dec(oi->type_pkg); + SvREFCNT_dec(oi->type_meth); +#endif /* !LT_MULTIPLICITY */ } +#if LT_MULTIPLICITY + { + STRLEN op_len = SvCUR(orig_pkg); + STRLEN tp_len = SvCUR(type_pkg); + STRLEN tm_len = SvCUR(type_meth); + STRLEN new_buf_size = op_len + tp_len + tm_len; + char *buf; + if (new_buf_size > oi->buf_size) { + PerlMemShared_free(oi->buf); + oi->buf = PerlMemShared_malloc(new_buf_size); + oi->buf_size = new_buf_size; + } + buf = oi->buf; + Copy(SvPVX(orig_pkg), buf, op_len, char); + buf += op_len; + Copy(SvPVX(type_pkg), buf, tp_len, char); + buf += tp_len; + Copy(SvPVX(type_meth), buf, tm_len, char); + oi->orig_pkg_len = op_len; + oi->type_pkg_len = tp_len; + oi->type_meth_len = tm_len; + } +#else /* LT_MULTIPLICITY */ oi->orig_pkg = orig_pkg; oi->type_pkg = type_pkg; oi->type_meth = type_meth; +#endif /* !LT_MULTIPLICITY */ + oi->pp_padsv = pp_padsv; #ifdef USE_ITHREADS @@ -393,20 +432,40 @@ STATIC OP *lt_pp_padsv(pTHX) { SV *sv = PAD_SVl(targ); if (sv) { + SV *orig_pkg, *type_pkg, *type_meth; int items; dSP; ENTER; SAVETMPS; +#if LT_MULTIPLICITY + { + STRLEN op_len = oi.orig_pkg_len, tp_len = oi.type_pkg_len; + char *buf = oi.buf; + orig_pkg = sv_2mortal(newSVpvn(buf, op_len)); + SvREADONLY_on(orig_pkg); + buf += op_len; + type_pkg = sv_2mortal(newSVpvn(buf, tp_len)); + SvREADONLY_on(type_pkg); + buf += tp_len; + type_meth = sv_2mortal(newSVpvn(buf, oi.type_meth_len)); + SvREADONLY_on(type_meth); + } +#else /* LT_MULTIPLICITY */ + orig_pkg = oi.orig_pkg; + type_pkg = oi.type_pkg; + type_meth = oi.type_meth; +#endif /* !LT_MULTIPLICITY */ + PUSHMARK(SP); EXTEND(SP, 3); - PUSHs(oi.type_pkg); + PUSHs(type_pkg); PUSHs(sv); - PUSHs(oi.orig_pkg); + PUSHs(orig_pkg); PUTBACK; - items = call_sv(oi.type_meth, G_ARRAY | G_METHOD); + items = call_sv(type_meth, G_ARRAY | G_METHOD); SPAGAIN; switch (items) { diff --git a/t/40-stress.t b/t/40-stress.t new file mode 100644 index 0000000..16fd887 --- /dev/null +++ b/t/40-stress.t @@ -0,0 +1,19 @@ +#!perl -T + +use strict; +use warnings; + +my $count; +BEGIN { $count = 1_000 } + +use Test::More tests => $count; + +sub Int::TYPEDSCALAR { join ':', (caller(0))[2], $_ } + +for (1 .. $count) { + eval q{ + use Lexical::Types; + my Int $x; + is $x, "3:$_", "run $_"; + } +}