diff options
author | M.J.T. Guy <mjtg@cus.cam.ac.uk> | 1997-12-20 16:19:46 +1200 |
---|---|---|
committer | Tim Bunce <Tim.Bunce@ig.co.uk> | 1998-05-16 02:18:52 +1200 |
commit | b4c4543f8946ff1747423a20d29d4ec5fff91c92 (patch) | |
tree | 2444336b1f6109af103b53a0e3e4724ca2a2f57e | |
parent | ab507278be50f43332e96c758826ae9174566218 (diff) | |
download | perl-b4c4543f8946ff1747423a20d29d4ec5fff91c92.tar.gz |
Avoid possible constant autoload loop
I attempted to install the SNMP-1.7 module, but 'make test' failed.
To find what was happening, I tried to run the particular test directly.
But I made the standard mistake of forgetting the -Iblib/auto on
the command line, so I quite rightly got
%perl5.004_04g -Iblib/lib t/session.t
Can't locate loadable object for module SNMP in @INC (@INC contains: blib/lib /home/mjtg/perl5.004_04g/lib /home/mjtg/perl5.004_04g/lib /home/mjtg/perl5.004_04g/lib .) at t/session.t line 12
BEGIN failed--compilation aborted at t/session.t line 12.
But then it went into a loop, which I didn't expect.
This is because
i) SNMP.pm has an END {} subroutine, which is (of course) installed
at compile time.
END{SNMP::_sock_cleanup();}
ii) It incorporates the constant autoloader from XS:
sub AUTOLOAD {
# This AUTOLOAD is used to 'autoload' constants from the constant()
# XS function. If a constant is not found then control is passed
# to the AUTOLOAD in AutoLoader.
my($val,$pack,$file,$line);
local($constname);
($constname = $AUTOLOAD) =~ s/.*:://;
$val = constant($constname, @_ ? $_[0] : 0);
if ($! != 0) {
if ($! =~ /Invalid/) {
$AutoLoader::AUTOLOAD = $AUTOLOAD;
goto &AutoLoader::AUTOLOAD;
}
else {
($pack,$file,$line) = caller;
die "Your vendor has not defined SNMP macro $constname, used at $file line $line.
";
}
}
eval "sub $AUTOLOAD { $val }";
goto &$AUTOLOAD;
}
So when the compilation fails, the END subroutine is called. Since the
subroutine _sock_cleanup isn't defined, AUTOLOAD is called. But since
the subroutine constant isn't defined, we now go into an AUTOLOAD
recursion.
An obvious fix is to defer establishing the END{} subroutine by putting it
inside an eval '' - patch attached.
But this style must be common to very many modules, so it seems worth
considering more general fixes.
a) Should END{} subroutines be run if compilation fails?
I suggest that END{} subroutines should not be installed
immediately on compilation, but should be placed on a deferred
list, and only moved to the main list on completion of
compilation.
b) The XS constant autoloader should check for the particular name
"constant" and die. Again patch attached.
But of course this patch won't be effective, since historical
copies of the autoloader are bound into every module in the
known universe. Why wasn't this made into a separate module
inherited by XS modules as required, in accordance with standard
world-saving procedures?
Credited: Graham Barr <gbarr@ti.com>
Credited: Ilya Zakharevich <ilya@math.ohio-state.edu>
p5p-msgid: E0ya11X-0000hm-00@taurus.cus.cam.ac.uk
-rw-r--r-- | utils/h2xs.PL | 1 |
1 files changed, 1 insertions, 0 deletions
diff --git a/utils/h2xs.PL b/utils/h2xs.PL index 800329103a..7d1a0da1f4 100644 --- a/utils/h2xs.PL +++ b/utils/h2xs.PL @@ -486,6 +486,7 @@ sub AUTOLOAD { my \$constname; (\$constname = \$AUTOLOAD) =~ s/.*:://; + croak "&$module::constant not defined" if \$constname eq 'constant'; my \$val = constant(\$constname, \@_ ? \$_[0] : 0); if (\$! != 0) { if (\$! =~ /Invalid/) { |