Closed p5pRT closed 17 years ago
"perldoc perlmod" says:
Like "CLONE"\, "CLONE_SKIP" is called once per package; however\, it is called just before cloning starts\, and in the context of the parent thread. If it returns a true value\, then no objects of that class will be cloned; or rather\, they will be copied as unblessed\, undef values.
But in my tests\, the copies are unblessed\, but aren't undef. Here's a simple example:
## Class.pm:
package Class;
use strict;
sub CLONE_SKIP { 1 }
sub new { bless {} }
1;
## cloneskip.pl:
#!/usr/bin/perl -W use strict; use Class; use threads;
my $obj = Class->new();
sub check_obj { my $where = shift; print "$where: ref(\$obj) = ".ref($obj)."\n"; print "$where: defined(\$obj) = ".defined($obj)."\n\n"; }
check_obj("main"); my $thread1 = threads->create(sub { check_obj("thread"); 1; } ); $thread1->join(); check_obj("main");
Output from "perl clone_skip.pl":
main: ref($obj) = Class main: defined($obj) = 1
thread: ref($obj) = SCALAR thread: defined($obj) = 1
main: ref($obj) = Class main: defined($obj) = 1
The documentation leads me to expect the third and fourth non-blank lines should be:
thread: ref($obj) = thread: defined($obj) =
as that is what I get if I change cloneskip.pl to do this:
my $thread1 = threads->create(sub { $obj = undef; check_obj("thread"); 1; } );
The documented behaviour seems sensible\, so I think the bug here is in the implementation rather than the documentation.
Cheers\, Olly
On Tue\, Oct 30\, 2007 at 07:40:27PM -0700\, Olly Betts wrote:
"perldoc perlmod" says:
Like "CLONE"\, "CLONE\_SKIP" is called once per package; however\, it is called just before cloning starts\, and in the context of the parent thread\. If it returns a true value\, then no objects of that class will be cloned; or rather\, they will be copied as unblessed\, undef values\.
But in my tests\, the copies are unblessed\, but aren't undef. Here's a simple example:
The documentation is ambiguous\, but the current behaviour of perl is as designed. References are cloned\, but in the child thread they are references to undefined scalars rather than blessed hashes or whatever; eg
use threads; sub CLONE_SKIP {1} my $x = bless {}; use Data::Dumper; print Dumper $x; threads->new(sub { print Dumper $x })->join;
gives:
$VAR1 = bless( {}\, 'main' ); $VAR1 = \undef;
However\, looking at the code I noticed that there *is* a bug\, in that the flags of the new undef scalar aren't zeroed (they're the same as the parent object)\, so the change below fixes that and tries to improve the documentation:
Change 32213 by davem@davem-pigeon on 2007/11/02 23:59:27
[perl #47045] CLONE_SKIP doesn't result in undef copies clarify the documentation on CLONE_SKIP\, and ensure that the undef value has all its flags cleared
Affected files ...
... //depot/perl/pod/perlmod.pod#42 edit ... //depot/perl/sv.c#1438 edit
Differences ...
==== //depot/perl/pod/perlmod.pod#42 (text) ====
@@ -581\,6 +581\,9 @@ called just before cloning starts\, and in the context of the parent thread. If it returns a true value\, then no objects of that class will be cloned; or rather\, they will be copied as unblessed\, undef values. +For example: if in the parent there are two references to a single blessed +hash\, then in the child there will be two references to a single undefined +scalar value instead. This provides a simple mechanism for making a module threadsafe; just add C\<sub CLONE_SKIP { 1 }> at the top of the class\, and C\<DESTROY()> will be now only be called once per object. Of course\, if the child thread needs
==== //depot/perl/sv.c#1438 (text) ====
@@ -10048\,8 +10048\,7 @@
/* don't clone objects whose class has asked us not to */ if (SvOBJECT(sstr) && ! (SvFLAGS(SvSTASH(sstr)) & SVphv_CLONEABLE)) { - SvFLAGS(dstr) &= ~SVTYPEMASK; - SvOBJECT_off(dstr); + SvFLAGS(dstr) = 0; return dstr; }
-- Technology is dominated by two types of people: those who understand what they do not manage\, and those who manage what they do not understand.
The RT System itself - Status changed from 'new' to 'open'
@iabyn - Status changed from 'open' to 'resolved'
Migrated from rt.perl.org#47045 (status was 'resolved')
Searchable as RT47045$