Skip Menu |
 

Preferred bug tracker

Please visit the preferred bug tracker to report your issue.

This queue is for tickets about the Storable CPAN distribution.

Report information
The Basics
Id: 11813
Status: new
Priority: 0/
Queue: Storable

People
Owner: Nobody in particular
Requestors: cpan [...] ali.as
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: 2.13
Fixed in: (no value)



Content-Type: text/plain
Content-Disposition: inline
Content-Transfer-Encoding: binary
MIME-Version: 1.0
X-Mailer: MIME-tools 5.415 (Entity 5.415)
Subject: Storable incompatible with singleton classes
X-RT-Original-Encoding: iso-8859-1
Content-Length: 2501
Download (untitled) / with headers
text/plain 2.4k
Storable spuriously creates illegal blessed hash references in STORABLE_thaw. This bug is related to bug #4901 and bug #6641, and will be fixed if point 2) from bug #6641 is implemented, but I'm adding it here as a seperate case, primarily because I've encapsulared the issue as a test case you can add to the Storable dist. ------------------------------------------------ singleton.t ------------------------------------------------ #!/usr/bin/perl -w # Tests the freezing/thawing structures containing Singleton objects, # which should see both structs pointing to the same object. # In order to make this test work, ANY method needs to exist that can # be used in STORABLE_freeze and STORABLE_thaw in order to make the tests # pass. use Storable (); use Test::More tests => 7; # Get the singleton my $object = My::Singleton->new; isa_ok( $object, 'My::Singleton' ); # Confirm (for the record) that the class is actually a Singleton my $object2 = My::Singleton->new; isa_ok( $object2, 'My::Singleton' ); is( "$object", "$object2", 'Class is a singleton' ); ############ # Main Tests my $struct = [ 1, $object, 3 ]; # Freeze the struct my $frozen = Storable::freeze( $struct ); ok( (defined($frozen) and ! ref($frozen) and length($frozen)), 'freeze returns a string' ); # Thaw the struct my $thawed = Storable::thaw( $frozen ); # Now it should look exactly like the original is_deeply( $struct, $thawed, 'Struct superficially looks like the original' ); # ... EXCEPT that the Singleton should be the same instance of the object is( "$struct->[1]", "$thawed->[1]", 'Singleton thaws correctly' ); # We can also test this empirically $struct->[1]->{value} = 'Goodbye cruel world!'; is_deeply( $struct, $thawed, 'Empiric testing corfirms correct behaviour' ); # End Tests ########### package My::Singleton; my $SINGLETON = undef; sub new { $SINGLETON or $SINGLETON = bless { value => 'Hello World!' }, $_[0]; } sub STORABLE_freeze { my $self = shift; # We don't actually need to return anything, but provide a null string # to avoid the null-list-return behaviour. return (''); } sub STORABLE_thaw { my ($obj, $string) = @_; # Get the Singleton object my $self = My::Singleton->new; ### IS THERE ANY POSSIBLE CODE FOR STORABLE_thaw THAT CAN ### BE USED TO PASS THE TESTS??? ### LET'S TRY TO DOCUMENTED WAY OF CREATING THE OBJECT %$obj = %$self; return; } # This one would work under the proposed changes to Storable sub STORABLE_thaw_new { My::Singleton->new; }
Content-Type: text/plain
Content-Disposition: inline
Content-Transfer-Encoding: binary
MIME-Version: 1.0
X-Mailer: MIME-tools 5.415 (Entity 5.415)
X-RT-Original-Encoding: iso-8859-1
Content-Length: 1594
Download (untitled) / with headers
text/plain 1.5k
Indeed, you've hit a limitation of the Storable engine. Fixing this to get the correct behavior requires great care because the reason Storable creates objects for you to fill is that it handles all the cross-referencing between ojects to make sure the proper topology is recreated. If you want to insist that a particular object instantiated by Storable be replaced by a singleton instance, then you need to inform the core about that. It's not practical to let STORABLE_thaw return an object of youts, because when the singleton reference was serialized, it pointed to some objects (maybe) that will be deserialized as well later on (or were already re-instantiated), unless you made your own custom STORABLE_freeze hook to supersede the default serialization. Patching the structure after is has been completely instantiated could be an option, but it may require a retraversal of the whole thing to break the references to the "singleton" and force them to point back to your instance. A way to inform the Storable core about that would be to call the core from within STORABLE_thaw and inform it about the fact that the object requires special treatment. A "cleanup" phase on the the structure recreated could then be performed whenever this core routine was called during deserialization, so as to not impose a penalty on the regular cases -- I mean, the problem you've hit is genuine but is not something all that common. My humble comments as the original author. I've not been following the recent developments of Perl, so maybe all what precedes is just stupid and irrelevant.
Content-Type: text/plain
Content-Disposition: inline
Content-Transfer-Encoding: binary
MIME-Version: 1.0
X-Mailer: MIME-tools 5.415 (Entity 5.415)
From: cpan [...] ali.as
X-RT-Original-Encoding: iso-8859-1
Content-Length: 635
Download (untitled) / with headers
text/plain 635b
Show quoted text
> Indeed, you've hit a limitation of the Storable engine. > > Fixing this to get the correct behavior requires great care
Correct. You might want to take a look at bug #4901, where most of the ongoing conversation relating to the changes that will be needed is being discussed. Fortunately, I'm not a strange to complex topology algorithms, since I've written some before to deal with manipulation of arbitrarily complex relational database data sets. After various comments from people here and in #perl, I think we have an idea for what will be needed, and I'll be whiteboarded up some sample topologies to have a play shortly.


This service is sponsored and maintained by Best Practical Solutions and runs on Perl.org infrastructure.

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.