… | |
… | |
55 | |
55 | |
56 | sub enabled() { |
56 | sub enabled() { |
57 | $AnyEvent::Watchdog::ENABLED |
57 | $AnyEvent::Watchdog::ENABLED |
58 | } |
58 | } |
59 | |
59 | |
60 | =item AnyEvent::Watchdog::restart [$timeout] |
60 | =item AnyEvent::Watchdog::restart_in [$timeout] |
61 | |
61 | |
62 | Tells the supervisor to restart the process when it exits, or forcefully |
62 | Tells the supervisor to restart the process when it exits (enable |
63 | after C<$timeout> seconds (minimum 1, maximum 255, default 60). |
63 | autorestart), or forcefully after C<$timeout> seconds (minimum 1, maximum |
|
|
64 | 255, default 60). |
64 | |
65 | |
65 | Calls C<exit 0> to exit the process cleanly. |
66 | This function disables the heartbeat, if it was enabled. Also, after |
|
|
67 | calling this function the watchdog will ignore any further requests until |
|
|
68 | the program has restarted. |
66 | |
69 | |
67 | =cut |
70 | Good to call before you intend to exit, in case your clean-up handling |
|
|
71 | gets stuck. |
68 | |
72 | |
|
|
73 | =cut |
|
|
74 | |
69 | sub restart(;$) { |
75 | sub restart_in(;$) { |
70 | my ($timeout) = @_; |
76 | my ($timeout) = @_; |
|
|
77 | |
|
|
78 | return unless $C; |
|
|
79 | |
|
|
80 | undef $HEARTBEAT_W; |
71 | |
81 | |
72 | $timeout = 60 unless defined $timeout; |
82 | $timeout = 60 unless defined $timeout; |
73 | $timeout = 1 if $timeout < 1; |
83 | $timeout = 1 if $timeout < 1; |
74 | $timeout = 255 if $timeout > 255; |
84 | $timeout = 255 if $timeout > 255; |
75 | |
85 | |
76 | syswrite $C, "\x01\x02" . chr $timeout; |
86 | syswrite $C, "\x01\x02" . chr $timeout; |
|
|
87 | |
|
|
88 | # now make sure we dont' send it any further requests |
|
|
89 | our $OLD_C = $C; undef $C; |
|
|
90 | } |
|
|
91 | |
|
|
92 | =item AnyEvent::Watchdog::restart [$timeout] |
|
|
93 | |
|
|
94 | Just like C<restart_in>, but also calls C<exit 0>. This means that this is |
|
|
95 | the ideal method to force a restart. |
|
|
96 | |
|
|
97 | =cut |
|
|
98 | |
|
|
99 | sub restart(;$) { |
|
|
100 | &restart_in; |
77 | exit 0; |
101 | exit 0; |
78 | } |
102 | } |
79 | |
103 | |
80 | =item AnyEvent::Watchdog::Util::autorestart [$boolean] |
104 | =item AnyEvent::Watchdog::Util::autorestart [$boolean] |
81 | |
105 | |
… | |
… | |
92 | =cut |
116 | =cut |
93 | |
117 | |
94 | sub autorestart(;$) { |
118 | sub autorestart(;$) { |
95 | my $AUTORESTART = !@_ || $_[0]; |
119 | my $AUTORESTART = !@_ || $_[0]; |
96 | |
120 | |
|
|
121 | return unless $C; |
|
|
122 | |
97 | unless (enabled) { |
123 | unless (enabled) { |
98 | warn "AnyEvent::Watchdog: watchdog not running, cannot enable autorestart, ignoring.\n" |
124 | warn "AnyEvent::Watchdog: watchdog not running, cannot enable autorestart, ignoring.\n" |
99 | if $AUTORESTART; |
125 | if $AUTORESTART; |
100 | |
126 | |
101 | $AUTORESTART = 0; |
127 | $AUTORESTART = 0; |
… | |
… | |
130 | warn "AnyEvent::Watchdog: watchdog not running, cannot enable heartbeat, ignoring.\n"; |
156 | warn "AnyEvent::Watchdog: watchdog not running, cannot enable heartbeat, ignoring.\n"; |
131 | return; |
157 | return; |
132 | } |
158 | } |
133 | |
159 | |
134 | $interval = 60 unless defined $interval; |
160 | $interval = 60 unless defined $interval; |
135 | $interval = 1 if $interval < 1; |
161 | $interval = 0 if $interval < 0; |
136 | $interval = 255 if $interval > 255; |
162 | $interval = 255 if $interval > 255; |
137 | |
163 | |
138 | syswrite $C, "\x03" . chr $interval; |
164 | syswrite $C, "\x03" . chr int $interval |
|
|
165 | if $C; |
139 | |
166 | |
140 | $HEARTBEAT_W = AE::timer (0, $interval * 0.5, sub { |
167 | $HEARTBEAT_W = $interval && AE::timer (0, $interval * 0.5, sub { |
141 | syswrite $C, "\x04"; |
168 | syswrite $C, "\x04" |
|
|
169 | if $C; |
142 | }); |
170 | }); |
143 | } |
171 | } |
144 | |
172 | |
145 | =item AnyEvent::Watchdog::on_exit { BLOCK; shift->() } |
173 | =item AnyEvent::Watchdog::on_exit { BLOCK; shift->() } |
146 | |
174 | |
… | |
… | |
195 | END { $AnyEvent::Watchdog::end && &$AnyEvent::Watchdog::end } |
223 | END { $AnyEvent::Watchdog::end && &$AnyEvent::Watchdog::end } |
196 | |
224 | |
197 | sub _exit { |
225 | sub _exit { |
198 | $EXIT_STATUS = $? unless defined $EXIT_STATUS; |
226 | $EXIT_STATUS = $? unless defined $EXIT_STATUS; |
199 | |
227 | |
|
|
228 | # we might have two END blocks trying to call us. |
200 | undef $AnyEvent::Watchdog::end; |
229 | undef $AnyEvent::Watchdog::end; |
|
|
230 | |
|
|
231 | if (enabled) { |
|
|
232 | undef $HEARTBEAT_W; |
|
|
233 | restart_in 60; |
|
|
234 | } |
201 | |
235 | |
202 | my $cv = AE::cv; |
236 | my $cv = AE::cv; |
203 | my $cb = sub { $cv->end }; |
237 | my $cb = sub { $cv->end }; |
204 | |
238 | |
205 | $cv->begin; |
239 | $cv->begin; |
… | |
… | |
212 | |
246 | |
213 | if (ref $EXIT_STATUS) { |
247 | if (ref $EXIT_STATUS) { |
214 | # signal |
248 | # signal |
215 | # reset to default, hopefully this overrides any C-level handlers |
249 | # reset to default, hopefully this overrides any C-level handlers |
216 | $SIG{$EXIT_STATUS->[0]} = 'DEFAULT'; |
250 | $SIG{$EXIT_STATUS->[0]} = 'DEFAULT'; |
|
|
251 | |
217 | eval { |
252 | eval { |
218 | # try to unblock |
253 | # try to unblock |
219 | require POSIX; |
254 | require POSIX; |
220 | |
255 | |
221 | my $set = POSIX::SigSet->new; |
256 | my $set = POSIX::SigSet->new; |
222 | $set->addset ($EXIT_STATUS->[1]); |
257 | $set->addset ($EXIT_STATUS->[1]); |
223 | POSIX::sigprocmask (POSIX::SIG_UNBLOCK (), $set); |
258 | POSIX::sigprocmask (POSIX::SIG_UNBLOCK (), $set); |
224 | }; |
259 | }; |
|
|
260 | |
225 | # now raise the signal |
261 | # now raise the signal |
226 | kill $EXIT_STATUS->[1], $$; |
262 | kill $EXIT_STATUS->[1], $$; |
227 | |
263 | |
228 | # well, if we can't force it even now, try exit 255 |
264 | # well, if we can't force it even now, try exit 255 |
229 | $? = 255; |
265 | $? = 255; |