Philip M. Gollucci wrote:
David Ihnen wrote:
1. Problem Description:

While developing with CGI::Application and utilizing Apache::Reload, we encountered an issue where our modules were not being succesfully reinitialized on reload. It was traced down to @ISA not containing the proper values after a 'use base' directive, but only on automatic reload, and freshly on perl 5.10, not our previous version of perl 5.8.8!
Are you able to try 5.8.9, its at least a smaller change set to look at if 5.8.9 breaks too.

No, not easily when I considered the mod_perl ramifications particularly. I did find a way around this particular problem on the web server though.

I noticed line 79. of base.pm

79 next if grep $_->isa($base), ($inheritor, @bases);

Experimentally, if I commented it out, the web server could reload properly! Score!

Hm. I know ->isa is a UNIVERSAL function. UNIVERSAL.pm is... not implimented in perl. Must be in the C code.

So I found UNIVERSAL.c

whose isa function implimentation said after some error checks essentially

ST(0) = boolSV(sv_derived_from(sv, name));


which function had the documentation

=head1 SV Manipulation Functions

=for apidoc sv_derived_from

Returns a boolean indicating whether the SV is derived from the specified class
I<at the C level>.  To check derivation at the Perl level, call C<isa()> as a
normal Perl method.

=cut


Ooh. at the **C** level. I bet the unload utility doesn't even *affect* the C level!

Those who understand perl C code might be better able to tell if unloading in the C levels is possible, a good idea, or just bad mojo. Having taken some medicine to deal with the C-inspired headache that inspection brought on, I returned to base.pm.

ISA is a package local variable list that lists the parents. In order to see all-the-parents, or replicate ->isa, I have to get the list of all the packages in ISA, all THEIR ISAs, and so on, as long as there are contents therein. And my scan will pay attention only to the interpreter state, not the C state...

I should be able to do that in perl easily enough.  PATCH

--- 510base.pm    2008-12-29 12:48:27.000000000 -0700
+++ /usr/share/perl/5.10.0/base.pm    2008-12-29 12:48:48.000000000 -0700
@@ -76,7 +76,20 @@
            warn "Class '$inheritor' tried to inherit from itself\n";
        }

-        next if grep $_->isa($base), ($inheritor, @bases);
+        my @classlist = ($inheritor, @bases);
+        foreach ($inheritor, @bases) {
+            my @parents = @$_::ISA;
+            do {
+                my $class = shift @parents;
+                foreach my $parent (@$class::ISA) {
+                    unless (grep { $_ eq $parent } @classlist) {
+                        push @classlist, $parent;
+                        push @parents, @$parent::ISA;
+                    }
+                }
+            } while (scalar @parents);
+        }
+        next if grep {$_ eq $base} @classlist;

        if (has_version($base)) {
            ${$base.'::VERSION'} = '-1, set by base.pm'

I know thats kind of ugly, and verbose, and maybe not very performant. But it works for the web server. Its not in any of the ISAs at re-require time so it does not skip loading the module even if the C HAS seen it before, and the application continues happily.

So at any rate, its a patch that works for my case (much as I hate patching base.pm) - and to my somewhat weak understanding of the C code implimentation, does the same thing in perl that the isa-iteration did in c. What is the proper path here?

David Ihnen
Perl Programmer
Norchem Laboratories, Inc

Reply via email to