ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/AnyEvent-Watchdog/Watchdog.pm
(Generate patch)

Comparing AnyEvent-Watchdog/Watchdog.pm (file contents):
Revision 1.6 by root, Sun Aug 30 17:20:27 2009 UTC vs.
Revision 1.7 by root, Tue Sep 1 14:52:07 2009 UTC

2 2
3AnyEvent::Watchdog - generic watchdog/program restarter 3AnyEvent::Watchdog - generic watchdog/program restarter
4 4
5=head1 SYNOPSIS 5=head1 SYNOPSIS
6 6
7 # MUST be use'd as the very first thing in the main program 7 # MUST be use'd as the very first thing in the main program,
8 # as it clones/forks the program before it returns.
8 use AnyEvent::Watchdog; 9 use AnyEvent::Watchdog;
9 10
10=head1 DESCRIPTION 11=head1 DESCRIPTION
11 12
12This module implements a watchdog that can repeatedly fork the program and 13This module implements a watchdog that can repeatedly fork the program and
21program. It will cause weird effects when used from another module, as 22program. It will cause weird effects when used from another module, as
22perl does not expect to be forked inside C<BEGIN> blocks. 23perl does not expect to be forked inside C<BEGIN> blocks.
23 24
24=head1 RECIPES 25=head1 RECIPES
25 26
26Use AnyEvent::Watchdog solely as a convinient on-demand-restarter: 27Use AnyEvent::Watchdog solely as a convenient on-demand-restarter:
27 28
28 use AnyEvent::Watchdog; 29 use AnyEvent::Watchdog;
29 30
30 # and whenever you wnat to restart (e.g. to upgrade code): 31 # and whenever you want to restart (e.g. to upgrade code):
32 use AnyEvent::Watchdog::Util;
31 AnyEvent::Watchdog::restart; 33 AnyEvent::Watchdog::Util::restart;
32 34
33Use AnyEvent::Watchdog to kill the program and exit when the event loop 35Use AnyEvent::Watchdog to kill the program and exit when the event loop
34fails to run for more than two minutes: 36fails to run for more than two minutes:
35 37
36 use AnyEvent::Watchdog qw(autorestart heartbeat=120); 38 use AnyEvent::Watchdog autorestart => 1, heartbeat => 120;
37 39
38Use AnyEvent::Watchdog to automatically restart the program 40Use AnyEvent::Watchdog to automatically kill (but not restart) the program when it fails
39when it fails to handle events for longer than 5 minutes: 41to handle events for longer than 5 minutes:
40 42
41 use AnyEvent::Watchdog qw(autorestart heartbeat=300); 43 use AnyEvent::Watchdog heartbeat => 300;
42 44
43=head1 VARIABLES/FUNCTIONS 45=head1 VARIABLES/FUNCTIONS
44 46
45The module supports the following variables and functions: 47This module is controlled via the L<AnyEvent::Watchdog::Util> module:
46 48
47=over 4 49 use AnyEvent::Watchdog::Util;
50
51 # attempt restart
52 AnyEvent::Watchdog::Util::restart;
53
54 # check if it is running
55 AnyEvent::Watchdog::Util::enabled
56 or croak "not running under watchdog!";
48 57
49=cut 58=cut
50 59
51package AnyEvent::Watchdog; 60package AnyEvent::Watchdog;
52 61
53# load modules we will use later anyways 62# load modules we will use later anyways
54use common::sense; 63use common::sense;
55 64
56use Carp (); 65use Carp ();
57 66
58our $VERSION = '0.9'; 67our $VERSION = '1.0';
59
60=item $AnyEvent::Watchdog::ENABLED
61
62This is true when the program is running under the regime of
63AnyEvent::Watchdog. Semi-obviously, you should I<NOT> C<use> or C<require>
64this module before looking at this variable, and neither should you try
65to load this module unless in the main program, rather use an idiom like
66this:
67
68 $AnyEvent::Watchdog::ENABLED
69 or die "watchdog not enabled...";
70 AnyEvent::Watchdog::restart (60); # MUST use ()
71
72Note that if this variable is defined, but false, then AnyEvent::Watchdog
73is running, but you are in the watchdog process - you probably did
74something very wrong in this case.
75
76=cut
77 68
78our $PID; # child pid 69our $PID; # child pid
79our $ENABLED = 0; 70our $ENABLED = 0; # also version
80our $AUTORESTART; # actually exit 71our $AUTORESTART; # actually exit
81our $HEARTBEAT;
82our ($P, $C); 72our ($P, $C);
83 73
84sub poll($) { 74sub poll($) {
85 (vec my $v, fileno $P, 1) = 1; 75 (vec my $v, fileno $P, 1) = 1;
86 CORE::select $v, undef, undef, $_[0] 76 CORE::select $v, undef, undef, $_[0]
226 # parent code 216 # parent code
227 close $C; 217 close $C;
228 server; 218 server;
229 } else { 219 } else {
230 # child code 220 # child code
231 $ENABLED = 1; 221 $ENABLED = 1; # also version
232 222
233 # restore seek offsets 223 # restore seek offsets
234 while (my ($k, $v) = each %SEEKPOS) { 224 while (my ($k, $v) = each %SEEKPOS) {
235 open my $fh, "<&$k" or next; 225 open my $fh, "<&$k" or next;
236 sysseek $fh, $v, 0; 226 sysseek $fh, $v, 0;
240 close $P; 230 close $P;
241 last; 231 last;
242 } 232 }
243} 233}
244 234
245=item AnyEvent::Watchdog::restart [$timeout]
246
247Tells the supervisor to restart the process when it exits, or forcefully
248after C<$timeout> seconds (minimum 1, maximum 255, default 60).
249
250Calls C<exit 0> to exit the process cleanly.
251
252=cut
253
254sub restart(;$) {
255 my ($timeout) = @_;
256
257 $timeout = 60 unless defined $timeout;
258 $timeout = 1 if $timeout < 1;
259 $timeout = 255 if $timeout > 255;
260
261 syswrite $C, "\x01\x02" . chr $timeout;
262 exit 0;
263}
264
265=item AnyEvent::Watchdog::autorestart [$boolean]
266
267=item use AnyEvent::Watchdog qw(autorestart[=$boolean])
268
269Enables or disables autorestart (initially disabled, default for
270C<$boolean> is to enable): By default, the supervisor will exit if the
271program exits or dies in any way. When enabling autorestart behaviour,
272then the supervisor will try to restart the program after it dies.
273
274Note that the supervisor will never autorestart when the child died with
275SIGINT or SIGTERM.
276
277=cut
278
279sub autorestart(;$) {
280 syswrite $C, !@_ || $_[0] ? "\x01" : "\x00";
281}
282
283=item AnyEvent::Watchdog::heartbeat [$interval]
284
285=item use AnyEvent::Watchdog qw(heartbeat[=$interval])
286
287Tells the supervisor to automatically kill the program if it doesn't
288react for C<$interval> seconds (minium 1, maximum 255, default 60) , then
289installs an AnyEvent timer the sends a regular heartbeat to the supervisor
290twice as often.
291
292Exit behaviour isn't changed, so if you want a restart instead of an exit,
293you have to call C<autorestart>.
294
295The heartbeat frequency can be changed as often as you want, an interval
296of C<0> disables the heartbeat check again.
297
298=cut
299
300sub heartbeat(;$) {
301 my ($interval) = @_;
302
303 $interval = 60 unless defined $interval;
304 $interval = 1 if $interval < 1;
305 $interval = 255 if $interval > 255;
306
307 syswrite $C, "\x03" . chr $interval;
308
309 require AE;
310 $HEARTBEAT = AE::timer (0, $interval * 0.5, sub {
311 syswrite $C, "\x04";
312 });
313}
314
315sub import { 235sub import {
316 shift; 236 shift;
317 237
318 for (@_) { 238 while (@_) {
319 if (/^autorestart(?:=(.*))?$/) { 239 my $k = shift;
320 autorestart defined $1 ? $1 : 1; 240
321 } elsif (/^heartbeat(?:=(.*))?$/) { 241 require AnyEvent::Watchdog::Util;
322 heartbeat $1; 242
243 if ($k eq "autorestart") {
244 AnyEvent::Watchdog::Util::autorestart (! ! shift);
245 } elsif ($k eq "heartbeat") {
246 AnyEvent::Watchdog::Util::heartbeat (shift || 60);
323 } else { 247 } else {
324 Carp::croak "AnyEvent::Watchdog: '$_' is not a valid import argument"; 248 Carp::croak "AnyEvent::Watchdog: '$_' is not a valid import argument";
325 } 249 }
326 } 250 }
327} 251}
328 252
329=back 253# used by AnyEvent::Watchdog::Util.
254our $end;
255END { $end && &$end }
330 256
331=head1 SEE ALSO 257=head1 SEE ALSO
332 258
333L<AnyEvent>. 259L<AnyEvent::Watchdg::Util>, L<AnyEvent>.
334 260
335=head1 AUTHOR 261=head1 AUTHOR
336 262
337 Marc Lehmann <schmorp@schmorp.de> 263 Marc Lehmann <schmorp@schmorp.de>
338 http://home.schmorp.de/ 264 http://home.schmorp.de/

Diff Legend

Removed lines
+ Added lines
< Changed lines
> Changed lines