summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--embed.fnc1
-rw-r--r--embed.h2
-rw-r--r--perl.c21
-rw-r--r--pp_ctl.c7
-rw-r--r--proto.h1
-rw-r--r--t/op/caller.t43
6 files changed, 66 insertions, 9 deletions
diff --git a/embed.fnc b/embed.fnc
index 37c7f2b98e..751b9aa42b 100644
--- a/embed.fnc
+++ b/embed.fnc
@@ -518,6 +518,7 @@ sR |bool |ingroup |Gid_t testgid|bool effective
: Used in toke.c
p |void |init_argv_symbols|int argc|NN char **argv
: Used in mg.c
+po |void |init_db_args
p |void |init_debugger
Ap |void |init_stacks
Ap |void |init_tm |NN struct tm *ptm
diff --git a/embed.h b/embed.h
index fffdedec1a..07aa965d29 100644
--- a/embed.h
+++ b/embed.h
@@ -331,6 +331,8 @@
#endif
#ifdef PERL_CORE
#define init_argv_symbols Perl_init_argv_symbols
+#endif
+#ifdef PERL_CORE
#define init_debugger Perl_init_debugger
#endif
#define init_stacks Perl_init_stacks
diff --git a/perl.c b/perl.c
index 0edad78b1f..d52d79f41e 100644
--- a/perl.c
+++ b/perl.c
@@ -3774,15 +3774,30 @@ S_forbid_setid(pTHX_ const char flag, const bool suidscript) /* g */
}
void
+Perl_init_dbargs(pTHX)
+{
+ AV *const args = PL_dbargs = GvAV(gv_AVadd((gv_fetchpvs("DB::args",
+ GV_ADDMULTI,
+ SVt_PVAV))));
+
+ if (AvREAL(args)) {
+ /* Someone has already created it.
+ It might have entries, and if we just turn off AvREAL(), they will
+ "leak" until global destruction. */
+ av_clear(args);
+ }
+ AvREAL_off(PL_dbargs); /* XXX should be REIFY (see av.h) */
+}
+
+void
Perl_init_debugger(pTHX)
{
dVAR;
HV * const ostash = PL_curstash;
PL_curstash = PL_debstash;
- PL_dbargs = GvAV(gv_AVadd((gv_fetchpvs("DB::args", GV_ADDMULTI,
- SVt_PVAV))));
- AvREAL_off(PL_dbargs);
+
+ Perl_init_dbargs(aTHX);
PL_DBgv = gv_fetchpvs("DB::DB", GV_ADDMULTI, SVt_PVGV);
PL_DBline = gv_fetchpvs("DB::dbline", GV_ADDMULTI, SVt_PVAV);
PL_DBsub = gv_HVadd(gv_fetchpvs("DB::sub", GV_ADDMULTI, SVt_PVHV));
diff --git a/pp_ctl.c b/pp_ctl.c
index a93d6dc2b0..57118a4aa7 100644
--- a/pp_ctl.c
+++ b/pp_ctl.c
@@ -1791,11 +1791,8 @@ PP(pp_caller)
AV * const ary = cx->blk_sub.argarray;
const int off = AvARRAY(ary) - AvALLOC(ary);
- if (!PL_dbargs) {
- PL_dbargs = GvAV(gv_AVadd(gv_fetchpvs("DB::args", GV_ADDMULTI,
- SVt_PVAV)));
- AvREAL_off(PL_dbargs); /* XXX should be REIFY (see av.h) */
- }
+ if (!PL_dbargs)
+ Perl_init_dbargs(aTHX);
if (AvMAX(PL_dbargs) < AvFILLp(ary) + off)
av_extend(PL_dbargs, AvFILLp(ary) + off);
diff --git a/proto.h b/proto.h
index 1fc11806e8..08cb30bd87 100644
--- a/proto.h
+++ b/proto.h
@@ -1164,6 +1164,7 @@ PERL_CALLCONV void Perl_init_argv_symbols(pTHX_ int argc, char **argv)
#define PERL_ARGS_ASSERT_INIT_ARGV_SYMBOLS \
assert(argv)
+PERL_CALLCONV void Perl_init_db_args(pTHX);
PERL_CALLCONV void Perl_init_debugger(pTHX);
PERL_CALLCONV void Perl_init_stacks(pTHX);
PERL_CALLCONV void Perl_init_tm(pTHX_ struct tm *ptm)
diff --git a/t/op/caller.t b/t/op/caller.t
index 27a55a8312..40782bee70 100644
--- a/t/op/caller.t
+++ b/t/op/caller.t
@@ -5,7 +5,7 @@ BEGIN {
chdir 't' if -d 't';
@INC = '../lib';
require './test.pl';
- plan( tests => 78 );
+ plan( tests => 80 );
}
my @c;
@@ -163,6 +163,47 @@ sub hint_fetch {
$results[10]->{$key};
}
+{
+ my $tmpfile = tempfile();
+
+ open my $fh, '>', $tmpfile or die "open $tmpfile: $!";
+ print $fh <<'EOP';
+#!perl -wl
+use strict;
+
+{
+ package KAZASH ;
+
+ sub DESTROY {
+ print "DESTROY";
+ }
+}
+
+@DB::args = bless [], 'KAZASH';
+
+print $^P;
+print scalar @DB::args;
+
+{
+ local $^P = shift;
+}
+
+@DB::args = (); # At this point, the object should be freed.
+
+print $^P;
+print scalar @DB::args;
+
+# It shouldn't leak.
+EOP
+
+ foreach (0, 1) {
+ my $got = runperl(progfile => $tmpfile, args => [$_]);
+ $got =~ s/\s+/ /gs;
+ like($got, qr/\s*0 1 DESTROY 0 0\s*/,
+ "\@DB::args doesn't leak with \$^P = $_");
+ }
+}
+
$::testing_caller = 1;
do './op/caller.pl' or die $@;