Alan M. Carroll wrote:
> I'm having a problem with error handling in an AUTOLOAD
> subroutine. Here's
> a (very) simplified version of the code that exhibits the bad
> behaviour plus a work around:
> 
> #!/usr/bin/perl -w
> use strict;
> 
> package Bob;
> 
> sub AUTOLOAD {
>      our %AUTOLOADED;
>      our $AUTOLOAD;
>      print 'Autoloading ', $AUTOLOAD, "\n";
>      no strict "refs";
>      if (not exists $AUTOLOADED{$AUTOLOAD}) {
>          $AUTOLOADED{$AUTOLOAD} = 1; # check it myself
>          goto &$AUTOLOAD if (*{$AUTOLOAD}{CODE});
>      }
>      '<br />Internal Error: Call to undefined subroutine "' .
> $AUTOLOAD . '"<br />';
> }
> 
> sub test {
>      1;
> }
> 
> package main;
> 
> print "Start\n";
> my $fptr;
> {
>      no strict "refs";
>      my $name = "Bob::nop";
>      print "Capturing name\n";
>      $fptr = \&$name;
> }

The above code is the direct cause of the problem. Your abuse of
symbolic refs has caused a symbol table entry to be created of type
CODE, but without any actual code. This results in the "goto &$AUTOLOAD"
statement recursively calling AUTOLOAD. When you take out your "# check
it myself" line, AUTOLOAD recurses infinitely. If you get rid of the
above code then it works as you seem to expect.

In fact it is difficult to see what you are trying to accomplish with
the "goto &$AUTOLOAD if (*{$AUTOLOAD}{CODE});" statement. If there was a
sub to call then that would have been called, and not AUTOLOAD.

I can't see why you are using symbolic refs. The usual advice is that
you should not use them. However, it is not clear what you are trying to
accomplish. You appear to want to prevent calling an undefined sub
causing a fatal error. Why would you want to do that?

> print "Calling test\n";
> print &Bob::test(), "\n";
> print "Calling none\n";
> print &Bob::none(), "\n";
> print "Calling nop\n";
> print &Bob::nop(), "\n";

Also, you shouldn't use '&' when calling a sub, unless you know what it
does.

> 
> If you run this, it will run cleanly but one should note that
> "Autoloading" is printed twice after "Calling nop" indicating that
> the AUTOLOAD subroutine re-entered. If you comment out the line
> marked "check it myself" then running this script will completely
> lock up the PERL 
> executable (it's
> so virulent that I crashed a webhost with it - the load
> average went from
> ~4 to over 200 in a matter of seconds. How a non-threaded perl script
> managed to push the load average up more than 1 I don't
> understand, but
> there you are).
> 
> The problem is that when the name 'Bob::nop' is "captured",
> some kind of
> CODE object is put in that symbol, even though it's not
> defined in the Bob
> package. The capturing is an artifact of a registration system where
> strings in text to be processed are identified with PERL
> subroutines to run
> so I can't avoid that. The goal would be to catch cases where
> the targeted
> PERL subroutine doesn't exist without having to explicitly
> load all of the
> packages.
> 
> Yet that renders me unable to check to see if the subroutine
> is really in
> the package. As far as I can tell, doing my own check is the
> only way to do
> this safely. Has anyone else seen this? Is it a known, common
> problem? I've done some searching but can't find any mention of it
> (although I may have just missed it in the noise).
> 
> I suppose the best solution is to tweak the registration to
> keep the string
> and when it is actually invoked, extract the package, do the
> 'require' and capture at that point. Still, this seems like odd
> behaviour. 
> 
> Run on Windows XP, ActiveState PERL 5.8.4 build 810.

HTH

-- 
Brian Raven
 


-----------------------------------------------------------------------
The information contained in this e-mail is confidential and solely 
for the intended addressee(s). Unauthorised reproduction, disclosure, 
modification, and/or distribution of this email may be unlawful. If you 
have received this email in error, please notify the sender immediately 
and delete it from your system. The views expressed in this message 
do not necessarily reflect those of LIFFE Holdings Plc or any of its subsidiary 
companies.
-----------------------------------------------------------------------


_______________________________________________
ActivePerl mailing list
[EMAIL PROTECTED]
To unsubscribe: http://listserv.ActiveState.com/mailman/mysubs

Reply via email to