File Coverage

blib/lib/Sys/AlarmCall.pm
Criterion Covered Total %
statement 35 48 72.9
branch 16 30 53.3
condition 2 6 33.3
subroutine 5 5 100.0
pod 1 1 100.0
total 59 90 65.5


line stmt bran cond sub pod time code
1             package Sys::AlarmCall;
2             require Exporter;
3 1     1   843 use Carp qw(croak);
  1         1  
  1         104  
4             @ISA = qw(Exporter);
5             @EXPORT = qw(alarm_call);
6              
7 1     1   5 use vars qw($SCALAR_ERROR $ARRAY_ERROR $TIMEOUT);
  1         2  
  1         69  
8              
9 1     1   340 use strict;
  1         2  
  1         2750  
10              
11             # Documentation in pod format after __END__ token. See Perl
12             # man pages to convert pod format to man, html and other formats.
13              
14             $Sys::AlarmCall::VERSION = 1.2;
15              
16             my @ARG_STRINGS = (
17             '$_[0]',
18             '$_[0],$_[1]',
19             '$_[0],$_[1],$_[2]',
20             '$_[0],$_[1],$_[2],$_[3]',
21             '$_[0],$_[1],$_[2],$_[3],$_[4]',
22             '$_[0],$_[1],$_[2],$_[3],$_[4],$_[5]'
23             );
24              
25             $SCALAR_ERROR = 'ERROR ';
26             $ARRAY_ERROR = 'ERROR';
27             $TIMEOUT = 'TIMEOUT';
28              
29             sub _alarm_sig_handler {
30 1     1   27 die "Sys::AlarmCall::alarm_call went off\n";
31             }
32              
33             sub alarm_call {
34             # usage('INTEGER(>,0)','FUNCTION','LIST_OF_ARGUMENTS');
35 2     2 1 456 my $timeout = shift;
36 2         5 my $sub = shift;
37 2 50       10 $timeout >= 1 ||
38             croak("Sys::AlarmCall::alarm_call: Fatal error - timeout argument must be positive\n");
39 2         4 my($old_handler,$old_alarm,$wantarray,$remaining_alarm);
40 0         0 my($eval,$alarmed);
41              
42 2         25 $old_alarm = alarm(0);
43 2 50 33     8 if ( $old_alarm && ($timeout > $old_alarm) ) {
44 0         0 $timeout = $old_alarm;
45             }
46              
47 2         4 $wantarray = wantarray;
48 2         11 $old_handler = $SIG{'ALRM'};
49 2         32 $SIG{'ALRM'} = "Sys::AlarmCall::_alarm_sig_handler";
50 2 50 33     25 if (defined(ref($sub)) && (ref($sub) eq 'CODE') ) {
    50          
    50          
51 0         0 unshift(@_,$sub);
52 0         0 $sub = '&{shift(@_)}(@_);';
53             } elsif ($sub =~ m/^->/) {
54 0         0 unshift(@_,$sub);
55 0         0 $sub = 'shift(@_)' . $sub . '(@_);';
56             } elsif ($#_ < @ARG_STRINGS) {
57             ;#This is because many perl inbuilt functions won't compile
58             ;#if you just say func(@_) - they need to be given the
59             ;#proper number of arguments.
60 2         8 $sub .= '(' . $ARG_STRINGS[$#_] . ')' ;
61             } else {
62 0         0 $sub .= '(@_)';
63             }
64              
65 2         7 my ($callpack) = caller;
66 2         7 $eval = 'alarm(' . $timeout . ");\npackage " . $callpack . ";\n" . $sub;
67 2         4 my(@results,$results);
68 2 50       9 if ($wantarray) {
69 0         0 @results = eval $eval;
70             } else {
71 2         190 $results = eval $eval;
72             }
73 2         22 $remaining_alarm = alarm(0);
74 2         8 $alarmed = ($@ eq "Sys::AlarmCall::alarm_call went off\n");
75 2 100       11 if ($alarmed) {$remaining_alarm = 0}
  1         4  
76              
77 2 100       35 $SIG{'ALRM'} = $old_handler ? $old_handler : 'DEFAULT';
78              
79 2 50       6 if ( $old_alarm ) {;#There was a previous alarm pending
80 0         0 $old_alarm = $old_alarm - $timeout + $remaining_alarm;
81 0 0       0 if ($old_alarm > 0) {;#Reset it, excluding the elapsed time (at least)
82 0         0 alarm($old_alarm);
83             } else {;#It should have gone off already - so set it off
84 0         0 kill 'ALRM',$$;
85             }
86             }
87              
88             ;#Three things to think about:
89             ;#1. Did the eval fail due to some compile error or die call?
90             ;#2. Did the eval get timed out?
91             ;#3. Do we return an array or scalar?
92              
93 2 50       13 if ($alarmed) {return $wantarray ? ($TIMEOUT) : $TIMEOUT}
  1 0       18  
  0 100       0  
    50          
94             elsif ($@) {return $wantarray ? ($ARRAY_ERROR,$@) : $SCALAR_ERROR . $@}
95 1 50       16 $wantarray ? @results : $results;
96             }
97              
98              
99             1;
100             __END__