File Coverage

blib/lib/Sub/Timebound.pm
Criterion Covered Total %
statement 43 43 100.0
branch 6 6 100.0
condition n/a
subroutine 6 6 100.0
pod 0 1 0.0
total 55 56 98.2


line stmt bran cond sub pod time code
1             package Sub::Timebound;
2              
3 1     1   41836 use 5.008;
  1         3  
  1         522  
4 1     1   9 use strict;
  1         2  
  1         37  
5 1     1   6 use warnings;
  1         6  
  1         56  
6              
7             require Exporter;
8 1     1   1966 use AutoLoader qw(AUTOLOAD);
  1         1530  
  1         6  
9              
10             our @ISA = qw(Exporter);
11              
12             # Items to export into callers namespace by default. Note: do not export
13             # names by default without a very good reason. Use EXPORT_OK instead.
14             # Do not simply export all your public functions/methods/constants.
15              
16             # This allows declaration use Sub::Timebound ':all';
17             # If you do not need this, moving things directly into @EXPORT or @EXPORT_OK
18             # will save memory.
19             our %EXPORT_TAGS = ( 'all' => [ qw(
20            
21             ) ] );
22              
23             our @EXPORT_OK = ( @{ $EXPORT_TAGS{'all'} } );
24              
25             our @EXPORT = qw(timeboundretry);
26              
27             our $VERSION = '1.01';
28              
29             # Preloaded methods go here.
30              
31             sub timeboundretry
32             {
33             # Allocated Time, Attempts, Wait Time between attempts, Coderef to execute, Params
34 3     3 0 1035 my $allocated = int(shift);
35 3         5 my $attempts = int(shift);
36 3         6 my $wait = int(shift);
37 3         4 my $coderef = shift;
38 3         7 my @params = @_;
39              
40 3         11 my $ret = {
41             value => undef,
42             status => 1, ### Assume Success
43             };
44              
45 3         5 my $count = 1;
46              
47 3         10 my $ref_string = "Did not complete in allocated $allocated Seconds\n";
48              
49             AGAIN: {
50              
51 7         41 eval {
  7         21  
52 7     3   261 local $SIG{'ALRM'} = sub { die $ref_string };
  3         30000794  
53 7         176 alarm($allocated);
54 7         57 $ret->{value} = $coderef->(@params);
55 1         68 $ret->{status} = 1; ### We execute this means all is well
56 1         15 alarm(0); ### Reset alarm signal upon success
57             };
58              
59 7         136 alarm(0); ### Reset alarm signal
60              
61 7 100       33 if ($@) {
62 6         28 $ret->{status} = 0; ### Inform the caller that function call did not succeed
63             ### Now all we know is that eval block failed.
64             ### We still should determine if it died due to timeout or the called function misbehaved
65 6         809 print "ERROR $@\n";
66              
67 6 100       30 if ("$@" eq $ref_string) {
68 3         249 print "... Error happened due to timeout\n";
69             } else {
70 3         16 print "... Error happened due to function misbehavior\n";
71             }
72              
73 6         12 $count++;
74 6 100       21 if ($count > $attempts) {
75 2         112 print "Exceeded count limit ($attempts)....exiting\n";
76 2         16 return $ret;
77             } else {
78 4         152 print "Retry after $wait seconds...\n";
79 4         20001043 sleep $wait;
80 4         191 goto AGAIN;
81             }
82             }
83              
84             }
85 1         4 return $ret;
86             }
87              
88             # Autoload methods go after =cut, and are processed by the autosplit program.
89              
90             1;
91             __END__