summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorM.J.T. Guy <mjtg@cus.cam.ac.uk>1997-12-20 16:19:46 +1200
committerTim Bunce <Tim.Bunce@ig.co.uk>1998-05-16 02:18:52 +1200
commitb4c4543f8946ff1747423a20d29d4ec5fff91c92 (patch)
tree2444336b1f6109af103b53a0e3e4724ca2a2f57e
parentab507278be50f43332e96c758826ae9174566218 (diff)
downloadperl-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.PL1
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/) {