Mike Mike - 10 months ago 87
Perl Question

Inconsistent and inexplicable behavior in some perl files

Host is Linux. I have multiple files in the same directory. All of the

*.pl
files contain the following at the beginning differing only in comments:

#!/usr/bin/perl -w

BEGIN { chdir('/home/httpd/vhosts/mysite.com/httpdocs/newsbot'); unshift(@INC, "/home/httpd/vhosts/mysite.com/httpdocs/newsbot"); }

use Form;
use File;
use Mysite;

#Read in All Form Variables
&ReadInForm;


The file
Form.pm
contains the
ReadInForm
subroutine and nothing else.

sub ReadInForm {
}
1;


The weird thing is that the output of the above is completely inconsistent. Sometimes it executes fine, but shows the "Internal Server Error" message at the end of the script and puts the following in the
error_log
file:


Argument "" isn't numeric in subroutine entry at /usr/lib64/perl5/vendor_perl/5.8.8/x86_64-linux-thread-multi/ModPerl/RegistryCooker.pm line 171.\n, referer: http://www.mysite.com/newsbot/groupkeywords.pl


Other times, it doesn't execute, and outputs the following to the browser:


Undefined subroutine &ModPerl::ROOT::ModPerl::Registry::home_httpd_vhosts_mysite_2ecom_httpdocs_newsbot_groupkeywords_2epl::ReadInForm called at /home/httpd/vhosts/mysite.com/httpdocs/newsbot/groupkeywords.pl line 11.


Other times it works correctly with no error.

The strange thing is that it is inconsistent. I can get one output from a file, refresh a few minutes later and then get the other one. I've even got a few "Internal Server Error" messages and a 500 response header as well with no actual content. Commenting out the line
&ReadInForm;
solves the problem every time, so I have narrowed it down to that, however it doesn't matter what I put in
Form.pm
. I can even put an empty subroutine (as I have above) and it still doesn't solve the problem.

I am not even sure how to debug this. How is it even possible for it to be inconsistent? Does the perl compiler do some sort of behind the scenes caching?

Answer Source

Obviously your host is using Apache mod_perl. You must code explicitly for mod_perl. By the way your code smells of perl 4 and cgi-lib.pl, 1996 vintage. Simply put, under mod_perl your script can't work, because global variables are completely forbidden and you can't modify @INC under mod_perl anyway. You'd better put "use strict; use warnings;" in your script, and use proper CGI or mod_perl form parsing modules and functions.

However, this style of code should work:

#!/usr/bin/perl

# I don't know what this BEGIN block is for, but I suspect it may not work or causes subtle bugs...
BEGIN { chdir('/home/httpd/vhosts/mysite.com/httpdocs/newsbot'); }


use strict;
use warnings;
use Form;
use File;
use Mysite;

#Read in All Form Variables
Form::ReadInForm();

With this in Form.pm:

use strict;
use warnings;

package Form;

sub ReadInForm { 
}    
1;

Edit: if your code is old and you want to save you a major overhaul, you could create a "main" sub containing all of the script code and the variable declarations, and simply call it this way:

Old script:

#!/usr/bin/perl

# the following line will fail with "undeclared variable" under "use strict"
$a="test";
print "$a\n";

New script:

#!/usr/bin/perl

use strict; 
use warnings;

# call the main loop enclosing everything else    
main();

sub main {
    # first declare all variables
    my $a;

    # then add there all the code:
    $a="test";
    print "$a\n";
}

This way the script could be "modernized" cheaply and really quick.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download