Message-ID: <
20040107121357.GD82921@dansat.data-plan.com>
Returning a closure from a thread (via join) could mess up because
pointers to PL_sv_undef weren't rejigged to point at the joiner's
version of PL_sv_undef. Also, the closure's CvGV got cloned too
but never freed, since CvGV isn't refcounted.
p4raw-id: //depot/perl@22102
# call is() from within the DESTROY() function at global destruction time,
# and parts of Test::* may have already been freed by then
-print "1..8\n";
+print "1..9\n";
my $test : shared = 1;
}
)->join;
+# Returing a closure from a thread caused problems. If the last index in
+# the anon sub's pad wasn't for a lexical, then a core dump could occur.
+# Otherwise, there might be leaked scalars.
+
+sub f {
+ my $x = "foo";
+ sub { $x."bar" };
+}
+
+my $string = threads->new(\&f)->join->();
+print $string eq 'foobar' ? '' : 'not ', "ok $test - returning closure\n";
+$test++;
+
1;
{
ithread* current_thread;
AV* params = (AV*) SvRV(thread->params);
+ PerlInterpreter *other_perl = thread->interp;
CLONE_PARAMS clone_params;
clone_params.stashes = newAV();
clone_params.flags |= CLONEf_JOIN_IN;
PL_ptr_table = ptr_table_new();
current_thread = Perl_ithread_get(aTHX);
Perl_ithread_set(aTHX_ thread);
+ /* ensure 'meaningful' addresses retain their meaning */
+ ptr_table_store(PL_ptr_table, &other_perl->Isv_undef, &PL_sv_undef);
+ ptr_table_store(PL_ptr_table, &other_perl->Isv_no, &PL_sv_no);
+ ptr_table_store(PL_ptr_table, &other_perl->Isv_yes, &PL_sv_yes);
#if 0
{
SvREFCNT_inc(CvXSUBANY(sstr).any_ptr) :
sv_dup_inc(CvXSUBANY(sstr).any_ptr, param);
}
- CvGV(dstr) = gv_dup(CvGV(sstr), param);
+ /* don't dup if copying back - CvGV isn't refcounted, so the
+ * duped GV may never be freed. A bit of a hack! DAPM */
+ CvGV(dstr) = (param->flags & CLONEf_JOIN_IN) ?
+ Nullgv : gv_dup(CvGV(sstr), param) ;
if (param->flags & CLONEf_COPY_STACKS) {
CvDEPTH(dstr) = CvDEPTH(sstr);
} else {