ManFromNeptune has asked for the wisdom of the Perl Monks concerning the following question:

I've got a chunk of code that does database calls, text processing, math calculations, and more. Occasionally something 'hangs' and takes too long, so for debugging purposes I've wrapped the entire section (about 200 lines) in an eval { } with an alarm(). Problem is, when the alarm() trips, I don't know exactly where in the code Perl got hung up. Is there a way to know the 'line number' of code that was being processed when the alarm tripped? (Obviously I'm trying to *avoid* putting dozens of individual alarm()'s in the code...)

thanks,
MFN
  • Comment on determining the line# of code when an alarm() trips?

Replies are listed 'Best First'.
Re: determining the line# of code when an alarm() trips?
by almut (Canon) on Oct 18, 2007 at 19:58 UTC

    Have you tried Carp? Seems to work — at least for a simple case like this:

    #!/usr/bin/perl use Carp; eval { local $SIG{ALRM} = sub { croak "timed out" }; alarm 3; # ... # have it hang in line 12 my $s = <STDIN>; # ... alarm 0; }; print "$@\n" if $@;

    Output (if you let it time out):

    timed out at ./645816.pl line 6 main::__ANON__('ALRM') called at ./645816.pl line 12 eval {...} called at ./645816.pl line 12 eval {...} called at ./645816.pl line 5
Re: determining the line# of code when an alarm() trips?
by GrandFather (Saint) on Oct 18, 2007 at 19:52 UTC

    Is something like:

    use strict; use warnings; my $pos; $SIG{ALRM} = 'doReport'; alarm (2); eval {doFail ()}; sub doFail { while (1) { $pos = 1; $pos = 2; $pos = 3; $pos = 4; } } sub doReport { my ($package, $filename, $line, $subroutine) = caller 0; print "$line, $subroutine (pos = $pos)\n"; exit; }

    Prints:

    15, main::doReport (pos = 2)

    what you are looking for?


    Perl is environmentally friendly - it saves trees
Re: determining the line# of code when an alarm() trips?
by Fletch (Bishop) on Oct 18, 2007 at 19:12 UTC

    Not a direct answer to your question, but perhaps Devel::Trace (or simply running under the debugger) might show up the offending portion of code?

Re: determining the line# of code when an alarm() trips?
by ikegami (Patriarch) on Oct 18, 2007 at 19:11 UTC

    I don't know. The information is surely available somewhere (since the program needs to resume after the handler exits), but it might not be easy to obtain.

    You could trace the code using a debugger. Tracing displays each executed line as it is executed.

    Alternatively, you could do some manual tracing. Put a few print statements in strategic locations — don't forget to turn off buffering — and run the program. Now that you have a better idea where the problem is, put more print statements in that area and run the program again. Repeat this process until you locate the problem. This is the same idea behind binary searches.

Re: determining the line# of code when an alarm() trips?
by clueless newbie (Curate) on Oct 18, 2007 at 20:15 UTC
    If the 'offending' code is wrapped in the eval, then caller will tell you although you may have to dig a bit. If you move the code from Grandfather's sub into the eval and "dump" call in $SIG{ALRM} you will find a useful line number.
Re: determining the line# of code when an alarm() trips?
by oha (Friar) on Oct 19, 2007 at 09:43 UTC
    see caller:
    $SIG{ARLM} = sub { my ($package,$file,$line)=caller; print "ALRM at $file:$line\n"; };
    Oha