Re: Live_Objects behavior depends on garbage collection timing

[prev] [thread] [next] [Date index for 2004/07/09]

From: Siamak Pazirandeh
Subject: Re: Live_Objects behavior depends on garbage collection timing
Date: 19:12 on 09 Jul 2004
Thanks for the feedback. Tim, I looked further into the return value case, which leads to extended lifetime issues and came up with some conclusions/examples:


ex 1: This is the original case where the $user object persists.  This is the behavior I got on 5.8.0 and 5.8.2

do { my $user = Class::DBI::users->retrieve(1); };
print STDERR Class::DBI->dump_object_index();

$VAR1 = {
          'Class::DBI::users|user_id=1' => bless( {
                                                           'user_id' => '1'
                                                         }, 'Class::DBI::users' )
        };


---------------
ex 2: Fixed via Tim's "1":

do { my $user = Class::DBI::users->retrieve(1); 1; };
print STDERR Class::DBI->dump_object_index();

$VAR1 = {
          'Class::DBI::users|user_id=1' => undef
        };

---------------
ex 3: Now, this is unexpected. If I don't assign the object to a local var within the block, it will not persist!
do { Class::DBI::users->retrieve(1); };
print STDERR Class::DBI->dump_object_index();

$VAR1 = {
          'Class::DBI::users|user_id=1' => undef
        };
---------------
ex 4: This is the more serious case, which comes up with "has_a" relationships. probably the same issue as demonstrated in example 1, but actually implemented within the has_a behaviour:


In the following example, Class::DBI::html defines a "has_a" relationship to Class::DBI::card, on the primary key. You'll note that the card object persists. This is the original case which caused me to look into the issue. Very, Very subtle, but allows the object to remain as a Live_Object somehow. 

do {
my $card2=Class::DBI::card->retrieve(25189);
	if (my $hh=Class::DBI::html->retrieve(25189)) {
	$hh->html;
	}
};
print STDERR Class::DBI->dump_object_index();

$VAR1 = {
          'Class::DBI::html|cid=25189' => undef,
          'Class::DBI::card|cid=25189' => bless( {
                                                          'cid' => '25189'
                                                        }, 'Class::DBI::card' )
        };

-----------------

So it seems that under some subtle scenarios, perl allows returned references to persist, even if the L-value of the expression is, in C terms, void. That same issue may be responsible with the has_a issue in ex 4. I'd be great it if you could look into the has_a case, as I'm not very familiar with that code.

Thanks again for your prompt response.

Max



On Fri, Jul 09, 2004 at 01:07:29AM -0400, Perrin Harkins wrote:
> On Thu, 2004-07-08 at 19:16, Siamak Pazirandeh wrote:
> > Not so. There is another consideration, which is the timing of the
> > garbage collection. This can cause objects that have no reference to
> > them to still remain in the %Class::DBI::Live_Objects hash for some
> > undefined amount of time, until garbage collection sets the weakly
> > referenced objects to undef. In the meanwhile, any retrieves of that
> > object will grab from the cache or DB, unpredictably.
> 
> No offense, but how much do you know about the implementation of the
> garbage collector?  My impression has always been that there is no pause
> between the reference count on an object dropping to zero and that
> object being destroyed.  In fact, people write code that depends on
> this, where they assume that the DESTROY() method on their object will
> get called as soon as it goes out of scope.
> 
> I tried to reproduce your results with a variation of the code you
> posted, but could not.  It always showed that the value inside the
> %Live_Objects dump was undef.  I'm attaching my script to this message.
> 
> One thing that would be helpful is if you could change your
> dump_object_index() method to something like this:
> 
> sub dump_object_index {
>     use Devel::Peek;
>     my @defined = grep { defined } values %Live_Objects;
>     print Dump(\@defined);
> }
> 
> If you see anything in there with a REFCNT of 0, that means that
> Scalar::Util::weaken doesn't actually work the way we need it to, and we
> have to yank the "single instance" feature out of Class::DBI.  If you
> see things with REFCNT > 0, that means you still have references to them
> somewhere in your program.  If that's the case, and you can't find them,
> post some code and maybe we can help.
> 
> > It is understandable that a caching system based on weak refs will
> > have this kind of behavior.
> 
> (It's not a caching system!)
> 
> It's not understandable for a caching system based on reference counting
> to behave the way you're describing.  If it did, we would have
> out-of-scope objects behaving like legitimate in-scope data all over the
> place in lots of people's programs, and it would wreak havoc.  If I
> can't count on $cd being undefined when it's references have dropped to
> zero, that would be a pretty serious problem with Perl.
> 
> > For now, I am going to do as others on the list seem to be doing,
> > which is to override _init and turn off this caching behavior
> > alltogther.
> 
> Much simpler: set $Class::DBI::Weaken_Is_Available = 0 after loading
> Class::DBI.
> 
> I'm sorry to hear that you are having trouble with the single instance
> feature, and I hope you will reconsider trying to find the problem
> rather than just turning it off.
> 
> - Perrin


(message missing)

Re: Live_Objects behavior depends on garbage collection timing
Siamak Pazirandeh 19:12 on 09 Jul 2004

Generated at 11:35 on 01 Dec 2004 by mariachi v0.52