implement optional watchdog for remote connections
[scpubgit/Object-Remote.git] / lib / Object / Remote / WatchDog.pm
1 package Object::Remote::WatchDog; 
2
3 use Object::Remote::MiniLoop; 
4 use Object::Remote::Logging qw ( :log :dlog );
5 use Moo; 
6
7 BEGIN { 
8   $SIG{ALRM} = sub {
9     #if the Watchdog is killing the process we don't want any chance of the
10     #process not actually exiting and die could be caught by an eval which
11     #doesn't do us any good 
12     log_error { sprintf("Watchdog has expired, terminating the process at file %s line %s", __FILE__, __LINE__ + 1); };
13     exit(1);     
14   };   
15 };
16
17 has timeout => ( is => 'ro', required => 1 );
18
19 around new => sub {
20   my ($orig, $self, @args) = @_; 
21   our ($WATCHDOG);
22     
23   return $WATCHDOG if defined $WATCHDOG;
24   log_trace { "Constructing new instance of global watchdog" };
25   return $WATCHDOG = $self->$orig(@args);    
26 };
27
28 #start the watchdog
29 sub BUILD {
30   my ($self) = @_;
31   Dlog_debug { "Initializing watchdog with timeout of $_ seconds" } $self->timeout;
32   alarm($self->timeout);
33 }
34
35 #invoke at least once per timeout to stop
36 #the watchdog from killing the process 
37 sub reset {
38   our ($WATCHDOG);
39   die "Attempt to reset the watchdog before it was constructed"
40     unless defined $WATCHDOG; 
41   
42   log_trace { "Watchdog has been reset" };
43   alarm($WATCHDOG->timeout); 
44 }
45
46 #must explicitly call this method to stop the
47 #watchdog from killing the process - if the
48 #watchdog is lost because it goes out of scope
49 #it makes sense to still terminate the process
50 sub shutdown {
51   my ($self) = @_;
52   alarm(0); 
53 }
54
55 1;
56
57