develooper Front page | perl.perl5.porters | Postings from February 2003

Re: SvREFCNT_dec causing unexpected recursion

Nick Ing-Simmons
February 2, 2003 03:48
Re: SvREFCNT_dec causing unexpected recursion
Message ID:
Benjamin Goldberg <> writes:
>Nick Ing-Simmons wrote:
>> Benjamin Goldberg <> writes:
>> >"Anders Johnson (via RT)" wrote:
>> >[snip]
>> >> +              if(PL_psig_ptr[i]) {
>> >> +                      to_dec=PL_psig_ptr[i];
>> >> +                      PL_psig_ptr[i]=0;
>> >> +                      SvREFCNT_dec(to_dec);
>> >> +              }
>> >
>> >How often is stuff like this used/needed, throughout perl's source?
>> >It's not exactly something one can grep for, after all...
>> >
>> >I suspect (fear) that many places where this should be done, but
>> >isn't.
>> I don't fully grasp what the problem is yet. The "safe signals" code
>> in 5.8 should make the above _less_ necessary.
>I'm not speaking of signals 

Phew - we have enough trouble with those as it is :-(

>-- I'm speaking of places where perl's
>source code does SvREFCNT_dec on a 'reachable' pointer, without first
>replacing that pointer with either NULL or PL_sv_undef.

Hmm, you have to watch for spots where SvREFCNT_dec is normally just 
a decrement - blindly stuffing Nullsv in the slot may make things worse.

>> Signals should only be asynchronously messing with a always allocated
>> array of counts.
>> All access to perl SVs etc. should be synchronous - so what is
>> getting in during the decrement? And which bit of code let it?
>When the SV's refcount gets decremented all the way to zero, and that SV
>was blessed, it's DESTROY method gets called.
>That DESTROY could do stuff which then re-enters the bit of code which
>performed the decrement... the most obvious effect of this is "Attempt
>to free unreferenced scalar" warnings, but there may be other harmful

If I recall correctly there is a "coder beware" notice in docs of DESTROY
which says don't-do-that. But it would be good to fix the segfault part.

>   my ($x, @x) = 1;
>   sub DESTROY { print $x++,"\n"; undef @x }
>   @x = map { bless [] } 1..5;
>   undef @x;
>   __END__
>This code, under AS Perl 5.6.1, prints out 15 "Attempt to free
>unreferenced scalar" warnings, then produces a page fault.
>I haven't tested it with 5.8, but looking at the source of av_undef in
>bleedperl, I suspect it will happen there, too.
>> >Eg, av_clear stores sv_undef in the array slot before decrementing
>> >the refcount of that sv, but neither av_undef nor av_fill do.
>> >
>> >In gv_fetchmeth, I see:
>> >            SvREFCNT_dec(cv);
>> >            GvCV(topgv) = cv = Nullcv;
>> >Should this do something similar (replace, then dec?)?  I suppose
>> >that it's rare that coderefs get blessed at all, let alone into
>> >classes with destructors, so it would be hard to provoke this
>> >accidentally, but it's concievable.  There're other places throughout
>> >perl which likewise derecemnt before replacing.
>> >
>> >   perl -e '@x = (bless[]); sub DESTROY{pop @x}; undef @x'
>> >   perl -e '@x = (bless[]); sub DESTROY{pop @x}; $#x=-1'
>> >   perl -e '%x = (1,bless[]); sub DESTROY{ delete $x{1}; }; %x=()'
>> >
>> >Knowing that the problem exists, I'm sure that someone could come up
>> >with perl code which provokes the others.
Nick Ing-Simmons Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at | Group listing | About