This queue is for tickets about the Class-Std CPAN distribution.

Report information
The Basics
Id:
56567
Status:
open
Priority:
Low/Low
Queue:

People
Owner:
Nobody in particular
Requestors:
bulldogorama [...] gmail.com
Cc:
AdminCc:

BugTracker
Severity:
(no value)
Broken in:
(no value)
Fixed in:
(no value)



CC: Bulldog <bulldogorama@gmail.com>
Subject: Initialization failure with init_arg (possible race condition)
Date: Tue, 13 Apr 2010 11:55:58 -0700
To: bug-Class-Std@rt.cpan.org
From: Bulldog <bulldogorama@gmail.com>
The INITIALIZATION loop can fail to initialize properly using 'init_arg'.

Using a base class that has an :init_arg <events> and several subclasses.
Created an instance of <subclass_1> scoped to an 'if' block.
In a separate 'if' block immediately following, created an instance of a different subclass, <subclass_2>.
The instance of <subclass2> had the same 'events' attribute as the former instance of <subclass1>, even though the 'events' argument passed to the constructor was correct.
Naturally, this caused the instance of <subclass2> to behave incorrectly.
Inspection revealed that both instances had the same 'ident'.

I believe the issue is in http://cpansearch.perl.org/src/DCONWAY/Class-Std-0.011/lib/Class/Std.pm on line 446:
444        INITIALIZATION:
445 for my $attr_ref ( @{$attribute{$base_class}} ) {
446 next INITIALIZATION if defined $attr_ref->{ref}{$new_obj_id};
447
448 # Get arg from initializer list...
If there is a race condition between when DESTROY gets called (clearing the attribute for the previous instance) and when the initialization code is run, then I believe the condition for line 446 will be true and the old attribute will be preserved, corrupting the new object.

Thanks.

 - David Guy
Subject: Re: [rt.cpan.org #56567] Initialization failure with init_arg (possible race condition)
Date: Wed, 14 Apr 2010 19:40:52 +0100
To: bug-Class-Std@rt.cpan.org
From: Damian Conway <damian@conway.org>
Thanks, David. And especially for the excellent forensic work. I will look into a fix as soon as possible. All the best, Damian
Subject: Re: [rt.cpan.org #56567] Initialization failure with init_arg (possible race condition)
Date: Sat, 24 Apr 2010 12:20:36 +0200
To: bug-Class-Std@rt.cpan.org
From: Damian Conway <damian@conway.org>
Hi again, David. I've tried to reproduce your bug, but can't seem to cause the problem. The mystery seems to be why the destructor (which would normally clean up the 'events' data) is not being called at the end of the first block. I can certainly produce a work-around, but it simply shouldn't be needed. A given address shouldn't be reallocated, unless it wasn't de- allocated, and if it *was* de-allocated, its destructor should have been invoked immediately and done the cleanup. Could you please verify that the following code, which tries to reproduce what you reported, does indeed fail to work on your system. If it does work, could you send me back the simplest example you have of code that *doesn't* work. Thanks, Damian -----cut----------cut----------cut----------cut----------cut----- #! /usr/bin/perl -w use strict; { package BaseClass; use Class::Std; my %events_of : ATTR( :name<events> ); } { package Der1; use Class::Std; use base 'BaseClass'; sub DEMOLISH { print 'Der1 dtor', "\n" } } { package Der2; use Class::Std; use base 'BaseClass'; sub DEMOLISH { print 'Der2 dtor', "\n" } } if (1) { my $obj = Der1->new({ events=>42 }); print $obj, "\n"; print $obj->get_events, "\n"; } if (1) { my $obj = Der2->new({ events=>86 }); print $obj, "\n"; print $obj->get_events, "\n"; }
Subject: Re: [rt.cpan.org #56567] Initialization failure with init_arg (possible race condition)
Date: Mon, 26 Apr 2010 12:04:10 -0700
To: bug-Class-Std@rt.cpan.org
From: Bulldog <bulldogorama@gmail.com>
I have spent several hours trying to find simple code that will repro this error, but have been unable to do so.

The objects and the associated data for which I was seeing this issue were fairly complex. Unfortunately, I'm not yet intimately familiar with the inner workings of Perl destructors and how/when they are called.

It may be that the size and/or complexity of the data and/or objects caused a delay in calling the destructor. However, the incorrect behavior I observed was the same each time, rather than the random occurrence one would expect if it was a true race condition.

Unfortunately, since the actual code is work-related, I cannot give you that source, but for the record, as a workaround, I simply removed the 'init_arg' declaration and added the arg check and initialization explicitly to the BUILD method. This fixed the issue.

As a side note, I checked and we appear to be using Class::Std v0.0.9. I will look into updating our library to the current version.

In the meantime, you can probably close this bug report, since we cannot currently reproduce the error.
I will give you an update if/when I can provide such a repro that you can test yourself.

Thank you very much for your time.

 - David



On Sat, Apr 24, 2010 at 3:21 AM, damian@conway.org via RT <bug-Class-Std@rt.cpan.org> wrote:
Show quoted text
<URL: http://rt.cpan.org/Ticket/Display.html?id=56567 >

Hi again, David.

I've tried to reproduce your bug, but can't seem to cause the problem.

The mystery seems to be why the destructor (which would normally clean
up the 'events' data) is not being called at the end of the first block.
I can certainly produce a work-around, but it simply shouldn't be
needed. A given address shouldn't be reallocated, unless it wasn't de-
allocated, and if it *was* de-allocated, its destructor should have been
invoked immediately and done the cleanup.

Could you please verify that the following code, which tries to
reproduce what you reported, does indeed fail to work on your system. If
it does work, could you send me back the simplest example you have of
code that *doesn't* work.

Thanks,

Damian

-----cut----------cut----------cut----------cut----------cut-----

   #! /usr/bin/perl -w
   use strict;

   {
       package BaseClass;
       use Class::Std;

       my %events_of : ATTR( :name<events> );
   }

   {
       package Der1;
       use Class::Std;
       use base 'BaseClass';

       sub DEMOLISH { print 'Der1 dtor', "\n" }
   }

   {
       package Der2;
       use Class::Std;
       use base 'BaseClass';

       sub DEMOLISH { print 'Der2 dtor', "\n" }
   }

   if (1) {
       my $obj = Der1->new({ events=>42 });
       print $obj, "\n";
       print $obj->get_events, "\n";
   }

   if (1) {
       my $obj = Der2->new({ events=>86 });
       print $obj, "\n";
       print $obj->get_events, "\n";
   }


Subject: Re: [rt.cpan.org #56567] Initialization failure with init_arg (possible race condition)
Date: Thu, 29 Apr 2010 07:18:21 +1000
To: bug-Class-Std@rt.cpan.org
From: Damian Conway <damian@conway.org>
Show quoted text
> I have spent several hours trying to find simple code that will repro this > error, but have been unable to do so. > ... > In the meantime, you can probably close this bug report, since we > cannot currently reproduce the error. I will give you an update > if/when I can provide such a repro that you can test yourself.
I'm very sorry that the module has caused you this trouble, David. After all, it's designed to save time, not consume it. I have noted the potential problem and will be happy to revisit it if you eventually find a simple enough non-proprietary case that demonstrates the behaviour. Meanwhile, I'm glad you found a work-around, even if it is a little less convenient. All the best, Damian


This service runs on Request Tracker, is sponsored by The Perl Foundation, and maintained by Best Practical Solutions.

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