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

Hello - We have a random, recurring bug here at $work that is boggling my mind. Occasionally, when a bit of code tries to delegate to its SUPER class, the package name is somehow off by one random letter. Here's an example of the error message we're getting:

Can't locate object method "new" via package "MyCompany::Oages::TemplateConstants::SUPER" at MyCompany::Pages::TemplateConstants::new

This error is triggered by the following (slightly abbreviated) code:

package MyCompany::Pages::TemplateConstants; use strict; use warnings; use base qw(MyCompany::Interfaces::Object); # don't ask, it's lega +cy code sub new { my $class = shift; my $self = $class->SUPER::new(); # <--- randomly fails ... return $self; }

At the line where SUPER::new is called, the error is triggered. This code is executed thousands of times per day successfully but about once per day, it fails with the error listed above. The error varies slightly but there is always one letter in the class name that is "decremented" by one letter. In the specific case I pasted above, the P is turned into an O but it could be any letter in the class name. For instance, I've seen the following failures as well (in different classes but the same symptom):

MyCompany::Pages::TemplateObjectWraoper::SUPER
  vs.
MyCompany::Pages::TemplateObjectWrapper::SUPER

or

MyCompany::Pages::TemplateAbcount::SUPER
  vs.
MyCompany::Pages::TemplateAccount::SUPER

I can't understand how the value of $class would allow code execution to get into the correct new method but then when calling $class->SUPER::new it no longer provides the correct class to allow the @ISA traversal to work. In some instances, the invocant is a class name (i.e. $class as shown above) but in other times, it's a blessed reference (i.e. $self). The same error pops up in either case.

I'm not sure it's related to an incorrect @ISA but we are not (knowingly) modifying the contents of any classes @ISA array. I've grep'd through all of the CPAN modules we're using and I can't find anything that fiddles with a packages @ISA at this level (although I don't really know what to grep for in compiled C extensions).

I have not had the opportunity yet to put debugging code in our production environment to try and track down more specifically the state of $class/$self or @ISA. Are there any other bits of data that might be helpful to log in troubleshooting this issue?

We are using Perl v5.12.2.

Can anyone think of any possibilities for what is causing this bug?

Thanks for any help you might offer!

Replies are listed 'Best First'.
Re: SUPER delegation fails because class name getting munged (somehow?)
by moritz (Cardinal) on Feb 23, 2011 at 16:07 UTC
    Can anyone think of any possibilities for what is causing this bug?

    Memory corruption maybe. Are you using weird XS modules? Does the error also pop up for other perl versions?

    You can also try to usemro qw/c3/; and then $obj->next::method(@args) and see if the error goes away - if yes, it's really specific to SUPER

      We had this suspicion as well but it's hard to prove what might be the culprit since it's not readily reproducible. We did recently discover ImageMagick is seg-faulting when we run our app on a 64-bit OS so it's possible there may be some memory corruption going on there that doesn't result in a seg-fault on 32-bit.

      I'm not sure what qualifies as "weird" XS modules but scanning through the list of .so's I don't see anything sticking out. Everything we have is pretty standard CPAN stuff. This is mod_perl (v2.0.4) and Apache (2.2.17) however, so there's lots of stuff going on in the same memory space.

Re: SUPER delegation fails because class name getting munged (somehow?)
by Eliya (Vicar) on Feb 23, 2011 at 16:40 UTC

    As it always seems to be just one bit flipping, it could also be hardware-related memory corruption.

    I once had similar problems with very strange things happening occasionally.  At first, problems only occurred very seldomly, then more and more often. After quite a bit of hunting in the wrong places, it eventually turned out to be the power supply slowly getting flaky (voltage slowly dropping, and having more DC ripples than allowed).

    So, if you can take the machine down, run a memory tester (such as memtest86).

    Also, have maybe other strange things been happening on the machine?  For example, compiling huge programs has always been a good (indirect) "memory test" for me, as compilers tend to be quite sensitive to corrupted memory, and usually randomly crash as a result...

      O is decimal 79 is binary 01001111, P is decimal 80 is binary 01010000. So this is not bit flipping, there is something really substracting 1

        Ok, my fault.  The "argument" still holds, though, as hardware memory corruption mustn't necessarily result in only single bits flipping — it just happened to begin that way in the limited number of cases I've observed so far. I.e., the memtest statistics (after running for a couple of days) showed a clear pattern of certain "bit lines" flipping far more frequently than others.

Re: SUPER delegation fails because class name getting munged (somehow?)
by pajout (Curate) on Feb 23, 2011 at 16:10 UTC
    Just stupid idea: Can you show the code piece containing calling of that 'new' method?

    Update:

    I suspect something like

    use MyClass; my $obj = MyClass::new('MyBlass');

      Sure, it's very straightforward:

      $c->stash->{constant} = MyCompany::Pages::TemplateConstants->new($arg) +; # this is in Catalyst
        It looks good, I suspect static '::new' style with somehow munged first arg, but 'MyClass::MySubClass->new($args)' should be equivalent to 'MyClass::MySubClass::new("MyClass::MySubClass",$args)' (if method 'new' is implemented in MySubClass).
Re: SUPER delegation fails because class name getting munged (somehow?)
by DrHyde (Prior) on Feb 24, 2011 at 11:41 UTC
    <code>$class->SUPER...<code> is a bug in the general case, although in your specific case it should DTRT. SUPER is resolved *from the current package*, not from the object or class it appears to be called on.

      How is that a bug? My expectation would always be that SUPER is resolved in the context of the current package and that is the way it is documented in perlboot and perltoot along with pretty much anywhere else I've seen it mentioned in documentation.

      True laziness is hard work

        This was actually something that I've never really thought about and at first blush was surprising (although given five minutes of thought, it makes perfect sense). The fact that $class->SUPER::method() doesn't consider the value of $class at all could be unexepected since in typical use, the method is resolved relative to the invocant. Moose's bare super keyword avoids any confusion by removing the invocant altogether. This makes it (virtually) impossible to try and call some other class's (or object's) parent method via SUPER (or super in Moose's case).

Re: SUPER delegation fails because class name getting munged (somehow?)
by pajout (Curate) on Feb 23, 2011 at 16:36 UTC
    You can try
    sub new { my $class = shift; $class = ref($class) if ref($class); my $self = $class->SUPER::new(); # <--- randomly fails ... return $self; }