lom has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

I have a problem while using CGI::Session, when I try to store an object. After a few tests, I've isolated the problem.

I have got a class (Md), which contains a method param().

When I dump (data::Dumper) an object of this class, when I 'thaw' it with Safe (which basically do sandbox'ed eval), I get an object from the right class, but which can not execute param();

See following code for explanation:

#!/usr/bin/perl use strict; use Data::Dumper; use Safe; package Md; sub new {bless {'plop' => 'coin'}, $_[0]}; sub param {return $_[0]->{$_[1]};} package main; #Object and dump creation my $md = Md->new(); my $dump = Dumper($md); #'eval'ed dump my $mde = eval($dump); print defined $mde ? "Defined" : "undef"; # => print undef, bad #Dump 'Safe' eval my $mdr = Safe->new->reval( $dump ); print defined $mdr ? "Defined" : "undef"; # => print defined, good print $mdr->can('param') ? "yes" : "No"; # => print No. Why?

Why a Md object ($mdr) cannot execute one of the Md methods?

Notes:
I noticed that by using $Data::Dumper::Terse or without 'use strict' it is possible to restore the object as intended, but the problem is hidden inside CGI::Session, I thus cannot use these solutions.

Thanks for you help

Replies are listed 'Best First'.
Re: CGI::Session cannot read data from Data::Dumper
by perrin (Chancellor) on Oct 31, 2007 at 13:37 UTC
    I'd recommend you avoid using Safe. It's going to break things frequently. I also recommend you avoid using Data::Dumper for persistence. It's great for debugging, but Storable is much better for persistence, and CGI::Session supports it.
      Thanks, it seems that it will do the trick for what I need. However, this question remains: why $mdr, which is a Md object, cannot execute the param() method?
Re: CGI::Session cannot read data from Data::Dumper
by !1 (Hermit) on Oct 31, 2007 at 22:05 UTC

    Basically the problem is that Safe creates a new environment and the class into which your data has been blessed is not the same class that exists in our normal environment.

    use Safe; use Devel::Peek; my $r = 'bless \\ do { my $x = 0 }, "x"'; print Dump(eval $r); print Dump(Safe->new->reval($r)); print Dump(eval $r); print Dump(Safe->new->reval($r));

    Which outputs (on my machine at least):

    SV = RV(0x1847158) at 0x1830630 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x182fa48 SV = PVMG(0x18a9974) at 0x182fa48 REFCNT = 1 FLAGS = (PADBUSY,PADMY,OBJECT,IOK,pIOK) IV = 0 NV = 0 PV = 0 STASH = 0x18d8620 "x" SV = RV(0x1847188) at 0x18d8b24 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x18d8b00 SV = PVMG(0x18a8f34) at 0x18d8b00 REFCNT = 1 FLAGS = (PADBUSY,PADMY,OBJECT,IOK,pIOK) IV = 0 NV = 0 PV = 0 STASH = 0x18d8b54 "x" SV = RV(0x1847180) at 0x18d88fc REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x18d8920 SV = PVMG(0x18a90f4) at 0x18d8920 REFCNT = 1 FLAGS = (PADBUSY,PADMY,OBJECT,IOK,pIOK) IV = 0 NV = 0 PV = 0 STASH = 0x18d8620 "x" SV = RV(0x1847188) at 0x18d8b18 REFCNT = 1 FLAGS = (TEMP,ROK) RV = 0x18d8a28 SV = PVMG(0x18a90f4) at 0x18d8a28 REFCNT = 1 FLAGS = (PADBUSY,PADMY,OBJECT,IOK,pIOK) IV = 0 NV = 0 PV = 0 STASH = 0x18d8b90 "x"

    Notice how the stash has the same address for both the first and third runs. The second and fourth entries (those that are both from new Safe environments) have stashes where the address does not match either. This is because the x namespace in our environment is not the same as the one in either of the Safe compartments we created. I'm curious which version of CGI::Session you are using since I submitted a crummy fix that walks the structure and reblesses everything in place in the 4.x version (__walk in CGI::Session::Serialize::default).

      Thanks a lot for this explanation.

      I'm using the Debian testing CGI::Session (4.20):

      # $Id: Session.pm 353 2006-12-05 02:10:19Z markstos $
      $CGI::Session::VERSION = '4.20';

      __xwalk is definitely present.

        If you don't mind, could you tell me what this returns?

        use Safe; use Devel::Peek; my $x = bless \ do { my $a = 0 }, "x"; print Dump($x); my $y = Safe->new->reval('bless \\ do { my $a = 0 }, "x"'); print Dump($y); bless $y, ref $y; print Dump($y);