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

problems with Scalar::Util::weaken() and CLONE

From:
Stas Bekman
Date:
November 14, 2003 15:51
Subject:
problems with Scalar::Util::weaken() and CLONE
Message ID:
3FB56A6C.2040100@stason.org
Scalar::Util::weaken() proposed to use in the conjunction with the CLONE 
function to solve the problem of cloning non-perl objects suffers itself from 
cloning.

Here is an example:

#/tmp/weaken2
package main;
use threads;
use Scalar::Util;
my $data = "a";
my $obj = \$data;
my $copy = $obj;
Scalar::Util::weaken($copy);
threads->new(sub { print "thread started\n";})->detach for (1..1);
sleep 1;


% perl-5.8.1-ithread /tmp/weaken2
thread started
Attempt to free unreferenced scalar SV 0x8154f74.

Oops, a weakened $copy was cloned too, but its guts are now messed
up. What scalar do you ask is unreferenced? It's the magic that was
added by weaken() and cloned during perl_clone, that perl complains about. 
Here is a more complex program that proves that with Devel::Peek:

#/tmp/weaken
package Foo;

use strict;
use warnings;

use Scalar::Util;
use Devel::Peek;

my %objects;
sub new {
     my $data = "a";
     my $self = bless \$data, __PACKAGE__;
     my $copy = $self;
     Scalar::Util::weaken($copy);

     $objects{"$self"} = $copy;
     return $self;
}

sub DESTROY {
     warn "DESTROY\n";
}

sub CLONE {
     warn "CLONE is called";
     for my $key ( keys %objects) {
         my $self = delete $objects{$key};
         Dump $self;
     }
}

package main;
use threads;

my $obj = Foo->new;

threads->new(sub { print "thread started\n";})->detach for (1..1);
sleep 1;


% perl-5.8.1-ithread /tmp/weaken
CLONE is called at /tmp/weaken line 23.
SV = RV(0x8110b2c) at 0x815de1c
   REFCNT = 1
   FLAGS = (PADBUSY,PADMY,ROK)
   RV = 0x8156e1c
   SV = PVMG(0x8115e38) at 0x8156e1c
     REFCNT = 2
     FLAGS = (PADBUSY,PADMY,OBJECT,RMG,POK,pPOK)
     IV = 0
     NV = 0
     PV = 0x8157860 "a"\0
     CUR = 1
     LEN = 2
     MAGIC = 0x8157828
       MG_VIRTUAL = &PL_vtbl_backref
       MG_TYPE = PERL_MAGIC_backref(<)
       MG_FLAGS = 0x02
         REFCOUNTED
       MG_OBJ = 0x8156e28
       SV = PVAV(0x8153494) at 0x8156e28
         REFCNT = 1
         FLAGS = ()
         IV = 0
         NV = 0
         ARRAY = 0x8157848
         FILL = 0
         MAX = 3
         ARYLEN = 0x0
         FLAGS = (REAL)
         Elt No. 0
     STASH = 0x8156d2c   "Foo"
thread started
DESTROY
Attempt to free unreferenced scalar SV 0x8156e28 during global destruction.
DESTROY

As you can see  SV 0x8156e28 is:

       SV = PVAV(0x8153494) at 0x8156e28
         REFCNT = 1
         FLAGS = ()
         IV = 0
         NV = 0
         ARRAY = 0x8157848
         FILL = 0
         MAX = 3
         ARYLEN = 0x0
         FLAGS = (REAL)
         Elt No. 0

Any chance we can change perl to call Devel::Peek::Dump when producing:

    Attempt to free unreferenced scalar SV 0x8154f74.

would save us a lot of time, trying to figure out what SV went lost.

__________________________________________________________________
Stas Bekman            JAm_pH ------> Just Another mod_perl Hacker
http://stason.org/     mod_perl Guide ---> http://perl.apache.org
mailto:stas@stason.org http://use.perl.org http://apacheweek.com
http://modperlbook.org http://apache.org   http://ticketmaster.com




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