On Wed Aug 31 09:16:37 2011, sprout wrote: > On Tue Aug 30 09:46:32 2011, nicholas wrote: > > $ ./perl -Ilib dist/threads-shared/t/clone.t > > 1..34 > > ok 1 - Loaded > > ok 2 - number > > ok 3 - string > > ok 4 - 1 arg > > ok 5 - cloned string > > ok 6 - cloned scalar ref > > ok 7 - cloned scalar ref in thread > > ok 8 - Circular ref typ > > ok 9 - Circular ref > > ok 10 - Circular ref in thread > > Attempt to free unreferenced scalar: SV 0x91eeb0, Perl interpreter: > > 0x973840 at dist/threads-shared/t/clone.t line 86. > > Attempt to free unreferenced scalar: SV 0x91eec8, Perl interpreter: > > 0x973840 at dist/threads-shared/t/clone.t line 86. > > Attempt to free unreferenced scalar: SV 0x8d15b8, Perl interpreter: > > 0x973840 at dist/threads-shared/t/clone.t line 86. > > ok 11 - Cloned circular refs from thread > > ok 12 - Cloned array > > ok 13 - Clone mod > > ok 14 - Original array > > ok 15 - Clone mod in thread > > Attempt to free unreferenced scalar: SV 0x902d18, Perl interpreter: > > 0x74ce60 at dist/threads-shared/t/clone.t line 108. > > Attempt to free unreferenced scalar: SV 0x902d30, Perl interpreter: > > 0x74ce60 at dist/threads-shared/t/clone.t line 108. > > Attempt to free unreferenced scalar: SV 0x977fd8, Perl interpreter: > > 0x74ce60 at dist/threads-shared/t/clone.t line 108. > > ok 16 - Clone mod from thread > > > > [etc, no more warnings] > > > > The test case resists most attempts to simplify it - removing > > seemingly > > unrelated earlier blocks from the test case removes the warning. > > I’ve reduced it to this: > > use threads; > use threads::shared; > > use Devel::Peek; > Dump *DB::args; > > { > my %hsh = ('' => undef); > eval { > shared_clone(%hsh); > }; > } > > my $bar :shared = shared_clone($x); > > #{ > my $foo :shared; > $foo = shared_clone(\$foo); > threads->create(sub { > Dump *DB::args; > undef $foo > })->join(); > > #} > __END__ > > Those Dump statements I’m using for debugging. > > So far I’ve ascertained that: > 1) The first unreferenced scalar is an entry in @DB::args that has > already been used as an AV by the time the thread is started. > 2) It gets cloned by sv_dup (not _inc) when the thread starts, so it > ends up in param->unreferenced, and hence on the temps stack in the thread. > 3) When the thread exits, cv_undef ends up freeing it, because it is > somehow reused as a padlist, even though it’s on the temps stack still > with a refcount of one. I don’t know which cv it is. > 4) When the temps are freed, we get ‘Attempt to freed unreferenced scalar’. > > Any ideas where to look now? > Aha! In pad.c:Perl_padlist_dup: /* look for it in the table first. I *think* that it shouldn't be possible to find it there. Well, except for how Perl_sv_compile_2op() "works" :-( */ dstpad = (AV*)ptr_table_fetch(PL_ptr_table, srcpad); if (dstpad) return dstpad; No SvREFCNT_inc! commit 6de654a5795b6f7915432ff16bcdac0688492a9b Author: Nicholas Clark <nick@ccl4.org> Date: Thu Feb 25 14:21:18 2010 +0000 In Perl_padlist_dup() don't duplicate @_ or pads caused by recursion. CvDEPTH() is 0 in a new thread, so duplicating pads beyond the always-present first level is a waste of effort and memory. Adding SvREFCNT_inc makes one warning go away.Thread Previous | Thread Next