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

SvREFCNT_dec causing unexpected recursion

Thread Previous | Thread Next
From:
Benjamin Goldberg
Date:
February 1, 2003 19:05
Subject:
SvREFCNT_dec causing unexpected recursion
Message ID:
3E3C8D9A.E128D93B@earthlink.net
Nick Ing-Simmons wrote:
> 
> Benjamin Goldberg <goldbb2@earthlink.net> 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 -- 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.

> 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
effects.

   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.

-- 
$..='(?:(?{local$^C=$^C|'.(1<<$_).'})|)'for+a..4;
$..='(?{print+substr"\n !,$^C,1 if $^C<26})(?!)';
$.=~s'!'haktrsreltanPJ,r  coeueh"';BEGIN{${"\cH"}
|=(1<<21)}""=~$.;qw(Just another Perl hacker,\n);

Thread Previous | Thread Next


nntp.perl.org: Perl Programming lists via nntp and http.
Comments to Ask Bjørn Hansen at ask@perl.org | Group listing | About