develooper Front page | perl.perl5.porters | Postings from December 2004

Re: [perl #32967] [PATCH] Re: More B bugs: svref_2object

Thread Previous | Thread Next
From:
Alexey Tourbin
Date:
December 28, 2004 16:54
Subject:
Re: [perl #32967] [PATCH] Re: More B bugs: svref_2object
Message ID:
20041229005337.GE7824@solemn.turbinal.org
On Tue, Dec 28, 2004 at 04:01:49PM -0800, Stephen McCamant wrote:
> AT> Recently I reported this bug on perl5-porters mailing list.
> AT> As there seems to be no immediate interest to this bug,
> AT> I file it for future revision.  I assign severity=medium
> AT> because reference counting mechanism seems to be affected.
> 
> AT> Brief description: consequent svref_2object calls produce wrong
> AT> B objects in certain cases.  Detailed explanation and test cases
> AT> are available via the following links:
> 
> AT> http://www.nntp.perl.org/group/perl.perl5.porters/96593
> AT> http://www.nntp.perl.org/group/perl.perl5.porters/96600
> 
> I think your diagnosis is correct. The B module in general, and
> svref_2object in particular, does not increase the reference count of
> the SV and OP objects the B::SV and B::OP proxies point to, so bad
> things happen if the proxy is used after the underlying object is
> freed. (I bet with more experimentation you could get a segfault, for
> instance).

Okay, thanks a lot for this clarification.  Unfortunately I don't quite
grok reference counting mechanism in Perl (for now).  I just have a code
that has a kludge that apparently fixes the mechanism for perl-5.8.x.
The code is as follows:

[...]
	use B qw(svref_2object);
	our $perlbug32967 = \$version;
	my $v = sv_version(svref_2object(\$version));
	# process $v
[...]
use B qw(class);
sub sv_version ($) {
	my $sv = shift;
	my $class = class($sv);
	if ($class eq "IV" or $class eq "PVIV") {
		return $sv->int_value;
	}
	if ($class eq "NV" or $class eq "PVNV") {
		return $sv->NV;
	}
	if ($class eq "PVMG") {
		for (my $mg = $sv->MAGIC; $mg; $mg = $mg->MOREMAGIC) {
			next if $mg->TYPE ne "V";
			my @v = $mg->PTR =~ /(\d+)/g;
			return $v[0] + $v[1] / 1000 + $v[2] / 1000 / 1000;
		}
	}
	if ($sv->can("PV")) {
		my $v = $sv->PV;
		if ($v =~ /^\s*\.?\d/) {
			$v =~ s/_//g;
			return $v + 0;
		}
	}
	return undef;
}
__END__

You see, without referencing $version to global $perlbug32967 variable, 
I get a very wrong result (wrong SV object), as of perl-5.8.6.  And this
kludge has *no effect* on perl-5.6.1.

So I feel like there's still a subtle problem: I can't understand why
$version and/or svref_2object(\$version) is freed upon subsequent
sv_version() calls.  (Well, I only want to know how to fix my code.)

To examine the real code, you may want to take a look at
http://search.cpan.org/dist/rpm-build-perl/ (only PVMG version strings
seems to break things).  My original post has a very simple example, though.

> However, I think the best solution is "don't do that, then". B is
> intended for looking at the parse tree, which isn't generally in
> danger of going away, rather than for examining transient values. It
> wouldn't be out of the question to change B so that it always
> SvREFCNT_inc'd the SVs it wrapped, but it would be a fairly major
> change, with some tricky aspects (for instance, should it try to hide
> the increased count from the B::SV:REFCNT method?). Trying to
> reference count OPs would be harder, since most of them don't actually
> store a reference count.
> 
> The appended documentation patch attempts to explain that one
> shouldn't do what you tried to do.
> 
>  -- Stephen

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