Kev
Kev

Reputation: 119806

Perl try/catch block throws error in Error.pm

I have the following code in in a Perl script I'm writing:

#!/usr/bin/perl
use DBI;
use Getopt::Long;
use Time::HiRes;
use Error qw(:try);

....

my $starttime = Time::HiRes::time;

try {
    my $dbh = DBI->connect("dbi:Sybase:$server", $username, $password);
    $dbh->do("use $database");
    my $query="exec OfflineDatabaseReport";

    $row = $dbh->selectrow_hashref($query);

    $dbh->disconnect();
} catch Error with {
    print "boom";
    exit 1;
};
my $endtime = Time::HiRes::time;
my $timetaken = $endtime - $starttime;

The script worked fine until I wrapped the data access portion in the try...catch block. Now I get the following exception thrown:

Can't use string ("1316135985.90893") as a HASH ref while "strict refs" in use at /usr/lib/perl5/site_perl/5.8.8/Error.pm line 217.

I did try setting:

no strict "refs";

But I still get the same error. Am I being naive in my usage of a try/catch block here?

Upvotes: 1

Views: 3304

Answers (1)

tron
tron

Reputation: 56

This is how the parser sees the code:

try({ ... }, catch(Error, with({ ... }, my $endtime = Time::HiRes::time)));

Meaning, it passes the result of setting $endtime to Time::HiRes::time as the 2nd argument of the with BLOCK sub. Looking at the source of Error.pm, I see:

sub with (&;$) {
    @_
}

Which means with BLOCK,SCALAR is a valid argument list. All it does is pass the arguments up to catch, which interprets my $endtime = Time::HiRes::time as its $clauses. catch itself returns $clauses, which turns the whole statement into:

try({ ... }, my $endtime = Time::HiRes::time);

try assumes $clauses is a hashref, as you can see by the call to

$clauses->{'finally'}->()
    if(defined($clauses->{'finally'}));

So perl tries to use the value of Time::HiRes::time as a hashref, which it most certainly cannot, since it's actually a scalar with a value of "1316135985.90893".

So yeah, the semicolon at the end of the catch block.

Upvotes: 3

Related Questions