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