line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
1
|
|
|
|
|
|
|
package FCGI::Engine::ProcManager; |
2
|
2
|
|
|
2
|
|
38740
|
use Moose; |
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
3
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
use constant DEBUG => 0; |
5
|
|
|
|
|
|
|
|
6
|
|
|
|
|
|
|
use POSIX qw(SA_RESTART SIGTERM SIGHUP); |
7
|
|
|
|
|
|
|
|
8
|
|
|
|
|
|
|
use FCGI::Engine::Types; |
9
|
|
|
|
|
|
|
use MooseX::Daemonize::Pid::File; |
10
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
our $VERSION = '0.22'; |
12
|
|
|
|
|
|
|
our $AUTHORITY = 'cpan:STEVAN'; |
13
|
|
|
|
|
|
|
|
14
|
|
|
|
|
|
|
has 'role' => ( |
15
|
|
|
|
|
|
|
is => 'rw', |
16
|
|
|
|
|
|
|
isa => 'FCGI::Engine::ProcManager::Role', |
17
|
|
|
|
|
|
|
default => sub { 'manager' } |
18
|
|
|
|
|
|
|
); |
19
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
has 'start_delay' => ( |
21
|
|
|
|
|
|
|
is => 'rw', |
22
|
|
|
|
|
|
|
isa => 'Int', |
23
|
|
|
|
|
|
|
default => sub { 0 } |
24
|
|
|
|
|
|
|
); |
25
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
has 'die_timeout' => ( |
27
|
|
|
|
|
|
|
is => 'rw', |
28
|
|
|
|
|
|
|
isa => 'Int', |
29
|
|
|
|
|
|
|
default => sub { 60 } |
30
|
|
|
|
|
|
|
); |
31
|
|
|
|
|
|
|
|
32
|
|
|
|
|
|
|
has 'n_processes' => ( |
33
|
|
|
|
|
|
|
is => 'rw', |
34
|
|
|
|
|
|
|
isa => 'Int', |
35
|
|
|
|
|
|
|
default => sub { 0 } |
36
|
|
|
|
|
|
|
); |
37
|
|
|
|
|
|
|
|
38
|
|
|
|
|
|
|
has 'pidfile' => ( |
39
|
|
|
|
|
|
|
is => 'rw', |
40
|
|
|
|
|
|
|
isa => 'MooseX::Daemonize::Pid::File', |
41
|
|
|
|
|
|
|
# coerce => 1, |
42
|
|
|
|
|
|
|
); |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
has 'no_signals' => ( |
45
|
|
|
|
|
|
|
is => 'rw', |
46
|
|
|
|
|
|
|
isa => 'Bool', |
47
|
|
|
|
|
|
|
default => sub { 0 } |
48
|
|
|
|
|
|
|
); |
49
|
|
|
|
|
|
|
|
50
|
|
|
|
|
|
|
has 'sigaction_no_sa_restart' => (is => 'rw', isa => 'POSIX::SigAction'); |
51
|
|
|
|
|
|
|
has 'sigaction_sa_restart' => (is => 'rw', isa => 'POSIX::SigAction'); |
52
|
|
|
|
|
|
|
|
53
|
|
|
|
|
|
|
has 'signals_received' => ( |
54
|
|
|
|
|
|
|
is => 'rw', |
55
|
|
|
|
|
|
|
isa => 'HashRef', |
56
|
|
|
|
|
|
|
default => sub { +{} } |
57
|
|
|
|
|
|
|
); |
58
|
|
|
|
|
|
|
|
59
|
|
|
|
|
|
|
has 'manager_pid' => ( |
60
|
|
|
|
|
|
|
is => 'rw', |
61
|
|
|
|
|
|
|
isa => 'Int', |
62
|
|
|
|
|
|
|
); |
63
|
|
|
|
|
|
|
|
64
|
|
|
|
|
|
|
has 'server_pids' => ( |
65
|
|
|
|
|
|
|
traits => [ 'Hash' ], |
66
|
|
|
|
|
|
|
is => 'rw', |
67
|
|
|
|
|
|
|
isa => 'HashRef', |
68
|
|
|
|
|
|
|
clearer => 'forget_all_pids', |
69
|
|
|
|
|
|
|
default => sub { +{} }, |
70
|
|
|
|
|
|
|
handles => { |
71
|
|
|
|
|
|
|
'_add_pid' => 'set', |
72
|
|
|
|
|
|
|
'get_all_pids' => 'keys', |
73
|
|
|
|
|
|
|
'remove_pid' => 'delete', |
74
|
|
|
|
|
|
|
'has_pids' => 'count', |
75
|
|
|
|
|
|
|
'pid_count' => 'count', |
76
|
|
|
|
|
|
|
} |
77
|
|
|
|
|
|
|
); |
78
|
|
|
|
|
|
|
|
79
|
|
|
|
|
|
|
sub add_pid { (shift)->_add_pid( @_, 1 ) } |
80
|
|
|
|
|
|
|
|
81
|
|
|
|
|
|
|
has 'process_name' => (is => 'ro', isa => 'Str', default => sub { 'perl-fcgi' }); |
82
|
|
|
|
|
|
|
has 'manager_process_name' => (is => 'ro', isa => 'Str', default => sub { 'perl-fcgi-pm' }); |
83
|
|
|
|
|
|
|
|
84
|
|
|
|
|
|
|
## methods ... |
85
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
sub BUILD { |
87
|
|
|
|
|
|
|
my $self = shift; |
88
|
|
|
|
|
|
|
unless ($self->no_signals()) { |
89
|
|
|
|
|
|
|
$self->sigaction_no_sa_restart( |
90
|
|
|
|
|
|
|
POSIX::SigAction->new( |
91
|
|
|
|
|
|
|
'FCGI::Engine::ProcManager::sig_sub' |
92
|
|
|
|
|
|
|
) |
93
|
|
|
|
|
|
|
); |
94
|
|
|
|
|
|
|
$self->sigaction_sa_restart( |
95
|
|
|
|
|
|
|
POSIX::SigAction->new( |
96
|
|
|
|
|
|
|
'FCGI::Engine::ProcManager::sig_sub', |
97
|
|
|
|
|
|
|
undef, |
98
|
|
|
|
|
|
|
POSIX::SA_RESTART |
99
|
|
|
|
|
|
|
) |
100
|
|
|
|
|
|
|
); |
101
|
|
|
|
|
|
|
} |
102
|
|
|
|
|
|
|
} |
103
|
|
|
|
|
|
|
|
104
|
|
|
|
|
|
|
# this is the signal handler ... |
105
|
|
|
|
|
|
|
{ |
106
|
|
|
|
|
|
|
my $SIG_CODEREF; |
107
|
|
|
|
|
|
|
|
108
|
|
|
|
|
|
|
sub sig_sub { $SIG_CODEREF->(@_) if ref $SIG_CODEREF } |
109
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
sub clear_signal_handler { undef $SIG_CODEREF } |
111
|
|
|
|
|
|
|
|
112
|
|
|
|
|
|
|
sub setup_signal_handler { |
113
|
|
|
|
|
|
|
my $self = shift; |
114
|
|
|
|
|
|
|
$SIG_CODEREF = $self->role eq 'manager' |
115
|
|
|
|
|
|
|
? sub { defined $self && $self->manager_sig_handler(@_) } |
116
|
|
|
|
|
|
|
: sub { defined $self && $self->server_sig_handler(@_) }; |
117
|
|
|
|
|
|
|
} |
118
|
|
|
|
|
|
|
} |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
## main loop ... |
121
|
|
|
|
|
|
|
|
122
|
|
|
|
|
|
|
sub manage { |
123
|
|
|
|
|
|
|
my $self = shift; |
124
|
|
|
|
|
|
|
|
125
|
|
|
|
|
|
|
# skip to handling now if we won't be managing any processes. |
126
|
|
|
|
|
|
|
$self->n_processes or return; |
127
|
|
|
|
|
|
|
|
128
|
|
|
|
|
|
|
# call the (possibly overloaded) management initialization hook. |
129
|
|
|
|
|
|
|
$self->role("manager"); |
130
|
|
|
|
|
|
|
$self->manager_init; |
131
|
|
|
|
|
|
|
$self->notify("initialized"); |
132
|
|
|
|
|
|
|
|
133
|
|
|
|
|
|
|
my $manager_pid = $$; |
134
|
|
|
|
|
|
|
|
135
|
|
|
|
|
|
|
MANAGING_LOOP: while (1) { |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
# FIXME |
138
|
|
|
|
|
|
|
# we should tell the process that it is being |
139
|
|
|
|
|
|
|
# run under some kind of daemon, which will mean |
140
|
|
|
|
|
|
|
# that getppid will usually then return 1 |
141
|
|
|
|
|
|
|
# - SL |
142
|
|
|
|
|
|
|
#getppid() == 1 and |
143
|
|
|
|
|
|
|
# return $self->die("calling process has died"); |
144
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
$self->n_processes > 0 or |
146
|
|
|
|
|
|
|
return $self->die; |
147
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
# while we have fewer servers than we want. |
149
|
|
|
|
|
|
|
PIDS: while ($self->pid_count < $self->n_processes) { |
150
|
|
|
|
|
|
|
|
151
|
|
|
|
|
|
|
if (my $pid = fork) { |
152
|
|
|
|
|
|
|
# the manager remembers the server. |
153
|
|
|
|
|
|
|
$self->add_pid($pid); |
154
|
|
|
|
|
|
|
$self->notify("server (pid $pid) started"); |
155
|
|
|
|
|
|
|
|
156
|
|
|
|
|
|
|
} |
157
|
|
|
|
|
|
|
elsif (! defined $pid) { |
158
|
|
|
|
|
|
|
return $self->abort("fork: $!"); |
159
|
|
|
|
|
|
|
} |
160
|
|
|
|
|
|
|
else { |
161
|
|
|
|
|
|
|
$self->manager_pid($manager_pid); |
162
|
|
|
|
|
|
|
# the server exits the managing loop. |
163
|
|
|
|
|
|
|
last MANAGING_LOOP; |
164
|
|
|
|
|
|
|
} |
165
|
|
|
|
|
|
|
|
166
|
|
|
|
|
|
|
for (my $s = $self->start_delay; $s; $s = sleep $s) {}; |
167
|
|
|
|
|
|
|
} |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
# this should block until the next server dies. |
170
|
|
|
|
|
|
|
$self->wait; |
171
|
|
|
|
|
|
|
|
172
|
|
|
|
|
|
|
}# while 1 |
173
|
|
|
|
|
|
|
|
174
|
|
|
|
|
|
|
SERVER: |
175
|
|
|
|
|
|
|
|
176
|
|
|
|
|
|
|
# forget any children we had been collecting. |
177
|
|
|
|
|
|
|
$self->forget_all_pids; |
178
|
|
|
|
|
|
|
|
179
|
|
|
|
|
|
|
# call the (possibly overloaded) handling init hook |
180
|
|
|
|
|
|
|
$self->role("server"); |
181
|
|
|
|
|
|
|
$self->server_init; |
182
|
|
|
|
|
|
|
$self->notify("initialized"); |
183
|
|
|
|
|
|
|
|
184
|
|
|
|
|
|
|
# server returns |
185
|
|
|
|
|
|
|
return 1; |
186
|
|
|
|
|
|
|
} |
187
|
|
|
|
|
|
|
|
188
|
|
|
|
|
|
|
## initializers ... |
189
|
|
|
|
|
|
|
|
190
|
|
|
|
|
|
|
sub manager_init { |
191
|
|
|
|
|
|
|
my $self = shift; |
192
|
|
|
|
|
|
|
|
193
|
|
|
|
|
|
|
unless ($self->no_signals) { |
194
|
|
|
|
|
|
|
$self->setup_signal_actions(with_sa_restart => 0); |
195
|
|
|
|
|
|
|
$self->setup_signal_handler; |
196
|
|
|
|
|
|
|
} |
197
|
|
|
|
|
|
|
|
198
|
|
|
|
|
|
|
$self->change_process_name; |
199
|
|
|
|
|
|
|
|
200
|
|
|
|
|
|
|
eval { $self->pidfile->write }; |
201
|
|
|
|
|
|
|
$self->notify("Could not write the PID file because: $@") if $@; |
202
|
|
|
|
|
|
|
|
203
|
|
|
|
|
|
|
inner(); |
204
|
|
|
|
|
|
|
} |
205
|
|
|
|
|
|
|
|
206
|
|
|
|
|
|
|
sub server_init { |
207
|
|
|
|
|
|
|
my $self = shift; |
208
|
|
|
|
|
|
|
|
209
|
|
|
|
|
|
|
unless ($self->no_signals) { |
210
|
|
|
|
|
|
|
$self->setup_signal_actions(with_sa_restart => 0); |
211
|
|
|
|
|
|
|
$self->setup_signal_handler; |
212
|
|
|
|
|
|
|
} |
213
|
|
|
|
|
|
|
|
214
|
|
|
|
|
|
|
$self->change_process_name; |
215
|
|
|
|
|
|
|
|
216
|
|
|
|
|
|
|
inner(); |
217
|
|
|
|
|
|
|
} |
218
|
|
|
|
|
|
|
|
219
|
|
|
|
|
|
|
|
220
|
|
|
|
|
|
|
## hooks ... |
221
|
|
|
|
|
|
|
|
222
|
|
|
|
|
|
|
sub pre_dispatch { |
223
|
|
|
|
|
|
|
my $self = shift; |
224
|
|
|
|
|
|
|
|
225
|
|
|
|
|
|
|
$self->setup_signal_actions(with_sa_restart => 1) |
226
|
|
|
|
|
|
|
unless $self->no_signals; |
227
|
|
|
|
|
|
|
|
228
|
|
|
|
|
|
|
inner(); |
229
|
|
|
|
|
|
|
} |
230
|
|
|
|
|
|
|
|
231
|
|
|
|
|
|
|
sub post_dispatch { |
232
|
|
|
|
|
|
|
my $self = shift; |
233
|
|
|
|
|
|
|
|
234
|
|
|
|
|
|
|
$self->exit("safe exit after SIGTERM") |
235
|
|
|
|
|
|
|
if $self->received_signal("TERM"); |
236
|
|
|
|
|
|
|
|
237
|
|
|
|
|
|
|
$self->exit("safe exit after SIGHUP") |
238
|
|
|
|
|
|
|
if $self->received_signal("HUP"); |
239
|
|
|
|
|
|
|
|
240
|
|
|
|
|
|
|
if ($self->manager_pid and getppid() != $self->manager_pid) { |
241
|
|
|
|
|
|
|
$self->exit("safe exit: manager has died"); |
242
|
|
|
|
|
|
|
} |
243
|
|
|
|
|
|
|
|
244
|
|
|
|
|
|
|
$self->setup_signal_actions(with_sa_restart => 0) |
245
|
|
|
|
|
|
|
unless $self->no_signals; |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
inner(); |
248
|
|
|
|
|
|
|
} |
249
|
|
|
|
|
|
|
|
250
|
|
|
|
|
|
|
## utils ... |
251
|
|
|
|
|
|
|
|
252
|
|
|
|
|
|
|
# sig-handlers |
253
|
|
|
|
|
|
|
|
254
|
|
|
|
|
|
|
sub manager_sig_handler { |
255
|
|
|
|
|
|
|
my ($self, $name) = @_; |
256
|
|
|
|
|
|
|
if ($name eq "TERM") { |
257
|
|
|
|
|
|
|
$self->notify("received signal $name"); |
258
|
|
|
|
|
|
|
$self->die("safe exit from signal $name"); |
259
|
|
|
|
|
|
|
} |
260
|
|
|
|
|
|
|
elsif ($name eq "HUP") { |
261
|
|
|
|
|
|
|
# send a TERM to each of the servers, |
262
|
|
|
|
|
|
|
# and pretend like nothing happened.. |
263
|
|
|
|
|
|
|
if (my @pids = $self->get_all_pids) { |
264
|
|
|
|
|
|
|
$self->notify("sending TERM to PIDs, @pids"); |
265
|
|
|
|
|
|
|
kill TERM => @pids; |
266
|
|
|
|
|
|
|
} |
267
|
|
|
|
|
|
|
} |
268
|
|
|
|
|
|
|
else { |
269
|
|
|
|
|
|
|
$self->notify("ignoring signal $name"); |
270
|
|
|
|
|
|
|
} |
271
|
|
|
|
|
|
|
} |
272
|
|
|
|
|
|
|
|
273
|
|
|
|
|
|
|
sub server_sig_handler { |
274
|
|
|
|
|
|
|
my ($self, $name) = @_; |
275
|
|
|
|
|
|
|
$self->received_signal($name, 1); |
276
|
|
|
|
|
|
|
} |
277
|
|
|
|
|
|
|
|
278
|
|
|
|
|
|
|
sub received_signal { |
279
|
|
|
|
|
|
|
my ($self, $sig, $received) = @_; |
280
|
|
|
|
|
|
|
return $self->signals_received unless $sig; |
281
|
|
|
|
|
|
|
$self->signals_received->{$sig}++ if $received; |
282
|
|
|
|
|
|
|
return $self->signals_received->{$sig}; |
283
|
|
|
|
|
|
|
} |
284
|
|
|
|
|
|
|
|
285
|
|
|
|
|
|
|
sub change_process_name { |
286
|
|
|
|
|
|
|
my $self = shift; |
287
|
|
|
|
|
|
|
$0 = ($self->role eq 'manager' ? $self->manager_process_name : $self->process_name); |
288
|
|
|
|
|
|
|
} |
289
|
|
|
|
|
|
|
|
290
|
|
|
|
|
|
|
sub wait : method { |
291
|
|
|
|
|
|
|
my $self = shift; |
292
|
|
|
|
|
|
|
|
293
|
|
|
|
|
|
|
# wait for the next server to die. |
294
|
|
|
|
|
|
|
return if (my $pid = CORE::wait()) < 0; |
295
|
|
|
|
|
|
|
|
296
|
|
|
|
|
|
|
# notify when one of our servers have died. |
297
|
|
|
|
|
|
|
$self->remove_pid($pid) |
298
|
|
|
|
|
|
|
and $self->notify("server (pid $pid) exited with status $?"); |
299
|
|
|
|
|
|
|
|
300
|
|
|
|
|
|
|
return $pid; |
301
|
|
|
|
|
|
|
} |
302
|
|
|
|
|
|
|
|
303
|
|
|
|
|
|
|
## signal handling stuff ... |
304
|
|
|
|
|
|
|
|
305
|
|
|
|
|
|
|
sub setup_signal_actions { |
306
|
|
|
|
|
|
|
my $self = shift; |
307
|
|
|
|
|
|
|
my %args = @_; |
308
|
|
|
|
|
|
|
|
309
|
|
|
|
|
|
|
my $sig_action = (exists $args{with_sa_restart} && $args{with_sa_restart}) |
310
|
|
|
|
|
|
|
? $self->sigaction_sa_restart |
311
|
|
|
|
|
|
|
: $self->sigaction_no_sa_restart; |
312
|
|
|
|
|
|
|
|
313
|
|
|
|
|
|
|
POSIX::sigaction(POSIX::SIGTERM, $sig_action) |
314
|
|
|
|
|
|
|
|| $self->notify("sigaction: SIGTERM: $!"); |
315
|
|
|
|
|
|
|
POSIX::sigaction(POSIX::SIGHUP, $sig_action) |
316
|
|
|
|
|
|
|
|| $self->notify("sigaction: SIGHUP: $!"); |
317
|
|
|
|
|
|
|
} |
318
|
|
|
|
|
|
|
|
319
|
|
|
|
|
|
|
## notification ... |
320
|
|
|
|
|
|
|
|
321
|
|
|
|
|
|
|
sub notify { |
322
|
|
|
|
|
|
|
my ($self, $msg) = @_; |
323
|
|
|
|
|
|
|
$msg =~ s/\s*$/\n/; |
324
|
|
|
|
|
|
|
print STDERR "FastCGI: " . $self->role() . " (pid $$): " . $msg; |
325
|
|
|
|
|
|
|
} |
326
|
|
|
|
|
|
|
|
327
|
|
|
|
|
|
|
## error/exit handlers ... |
328
|
|
|
|
|
|
|
|
329
|
|
|
|
|
|
|
sub die : method { |
330
|
|
|
|
|
|
|
my ($self, $msg, $n) = @_; |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
# stop handling signals. |
333
|
|
|
|
|
|
|
$self->clear_signal_handler; |
334
|
|
|
|
|
|
|
$SIG{HUP} = 'DEFAULT'; |
335
|
|
|
|
|
|
|
$SIG{TERM} = 'DEFAULT'; |
336
|
|
|
|
|
|
|
|
337
|
|
|
|
|
|
|
$self->pidfile->remove |
338
|
|
|
|
|
|
|
|| $self->notify("Could not remove PID file: $!"); |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
# prepare to die no matter what. |
341
|
|
|
|
|
|
|
if (defined $self->die_timeout) { |
342
|
|
|
|
|
|
|
$SIG{ALRM} = sub { $self->abort("wait timeout") }; |
343
|
|
|
|
|
|
|
alarm $self->die_timeout; |
344
|
|
|
|
|
|
|
} |
345
|
|
|
|
|
|
|
|
346
|
|
|
|
|
|
|
# send a TERM to each of the servers. |
347
|
|
|
|
|
|
|
if (my @pids = $self->get_all_pids) { |
348
|
|
|
|
|
|
|
$self->notify("sending TERM to PIDs, @pids"); |
349
|
|
|
|
|
|
|
kill TERM => @pids; |
350
|
|
|
|
|
|
|
} |
351
|
|
|
|
|
|
|
|
352
|
|
|
|
|
|
|
# wait for the servers to die. |
353
|
|
|
|
|
|
|
while ($self->has_pids) { |
354
|
|
|
|
|
|
|
$self->wait; |
355
|
|
|
|
|
|
|
} |
356
|
|
|
|
|
|
|
|
357
|
|
|
|
|
|
|
# die already. |
358
|
|
|
|
|
|
|
$self->exit("dying: $msg", $n); |
359
|
|
|
|
|
|
|
} |
360
|
|
|
|
|
|
|
|
361
|
|
|
|
|
|
|
sub abort { |
362
|
|
|
|
|
|
|
my ($self, $msg, $n) = @_; |
363
|
|
|
|
|
|
|
$n ||= 1; |
364
|
|
|
|
|
|
|
$self->exit($msg, 1); |
365
|
|
|
|
|
|
|
} |
366
|
|
|
|
|
|
|
|
367
|
|
|
|
|
|
|
sub exit : method { |
368
|
|
|
|
|
|
|
my ($self, $msg, $n) = @_; |
369
|
|
|
|
|
|
|
$n ||= 0; |
370
|
|
|
|
|
|
|
|
371
|
|
|
|
|
|
|
# if we still have children at this point, |
372
|
|
|
|
|
|
|
# something went wrong. SIGKILL them now. |
373
|
|
|
|
|
|
|
kill KILL => $self->get_all_pids |
374
|
|
|
|
|
|
|
if $self->has_pids; |
375
|
|
|
|
|
|
|
|
376
|
|
|
|
|
|
|
$self->notify($msg); |
377
|
|
|
|
|
|
|
$@ = $msg; |
378
|
|
|
|
|
|
|
CORE::exit $n; |
379
|
|
|
|
|
|
|
} |
380
|
|
|
|
|
|
|
|
381
|
|
|
|
|
|
|
1; |
382
|
|
|
|
|
|
|
|
383
|
|
|
|
|
|
|
__END__ |
384
|
|
|
|
|
|
|
|
385
|
|
|
|
|
|
|
=pod |
386
|
|
|
|
|
|
|
|
387
|
|
|
|
|
|
|
=head1 NAME |
388
|
|
|
|
|
|
|
|
389
|
|
|
|
|
|
|
FCGI::Engine::ProcManager - module for managing FastCGI applications. |
390
|
|
|
|
|
|
|
|
391
|
|
|
|
|
|
|
=head1 DESCRIPTION |
392
|
|
|
|
|
|
|
|
393
|
|
|
|
|
|
|
This module is a refactoring of L<FCGI::ProcManager>, it behaves exactly the |
394
|
|
|
|
|
|
|
same, but the API is a little different. The function-oriented API has been |
395
|
|
|
|
|
|
|
removed in favor of object-oriented API. The C<pm_> prefix has been removed |
396
|
|
|
|
|
|
|
from the hook routines and instead they now use the C<augment> and C<inner> |
397
|
|
|
|
|
|
|
functionality from L<Moose>. More docs will come eventually. |
398
|
|
|
|
|
|
|
|
399
|
|
|
|
|
|
|
=head2 Signal Handling |
400
|
|
|
|
|
|
|
|
401
|
|
|
|
|
|
|
FCGI::Engine::ProcManager attempts to do the right thing for proper shutdowns. |
402
|
|
|
|
|
|
|
|
403
|
|
|
|
|
|
|
When it receives a SIGHUP, it sends a SIGTERM to each of its children, and |
404
|
|
|
|
|
|
|
then resumes its normal operations. |
405
|
|
|
|
|
|
|
|
406
|
|
|
|
|
|
|
When it receives a SIGTERM, it sends a SIGTERM to each of its children, sets |
407
|
|
|
|
|
|
|
an alarm(3) "die timeout" handler, and waits for each of its children to |
408
|
|
|
|
|
|
|
die. If all children die before this timeout, process manager exits with |
409
|
|
|
|
|
|
|
return status 0. If all children do not die by the time the "die timeout" |
410
|
|
|
|
|
|
|
occurs, the process manager sends a SIGKILL to each of the remaining |
411
|
|
|
|
|
|
|
children, and exists with return status 1. |
412
|
|
|
|
|
|
|
|
413
|
|
|
|
|
|
|
FCGI::Engine::ProcManager uses POSIX::sigaction() to override the default |
414
|
|
|
|
|
|
|
SA_RESTART policy used for perl's %SIG behavior. Specifically, the process |
415
|
|
|
|
|
|
|
manager never uses SA_RESTART, while the child FastCGI servers turn off |
416
|
|
|
|
|
|
|
SA_RESTART around the accept loop, but re-enstate it otherwise. |
417
|
|
|
|
|
|
|
|
418
|
|
|
|
|
|
|
The desired (and implemented) effect is to give a request as big a chance as |
419
|
|
|
|
|
|
|
possible to succeed and to delay their exits until after their request, |
420
|
|
|
|
|
|
|
while allowing the FastCGI servers waiting for new requests to die right |
421
|
|
|
|
|
|
|
away. |
422
|
|
|
|
|
|
|
|
423
|
|
|
|
|
|
|
=head1 METHODS |
424
|
|
|
|
|
|
|
|
425
|
|
|
|
|
|
|
I will fill this in more eventually, but for now if you really wanna know, |
426
|
|
|
|
|
|
|
read the source. |
427
|
|
|
|
|
|
|
|
428
|
|
|
|
|
|
|
=head1 SEE ALSO |
429
|
|
|
|
|
|
|
|
430
|
|
|
|
|
|
|
=over 4 |
431
|
|
|
|
|
|
|
|
432
|
|
|
|
|
|
|
=item L<FCGI::ProcManager> |
433
|
|
|
|
|
|
|
|
434
|
|
|
|
|
|
|
This module is a fork of the FCGI::ProcManager code, with lots of |
435
|
|
|
|
|
|
|
code cleanup as well as general Moosificaition. |
436
|
|
|
|
|
|
|
|
437
|
|
|
|
|
|
|
=back |
438
|
|
|
|
|
|
|
|
439
|
|
|
|
|
|
|
=head1 BUGS |
440
|
|
|
|
|
|
|
|
441
|
|
|
|
|
|
|
All complex software has bugs lurking in it, and this module is no |
442
|
|
|
|
|
|
|
exception. If you find a bug please either email me, or add the bug |
443
|
|
|
|
|
|
|
to cpan-RT. |
444
|
|
|
|
|
|
|
|
445
|
|
|
|
|
|
|
=head1 AUTHOR |
446
|
|
|
|
|
|
|
|
447
|
|
|
|
|
|
|
Stevan Little E<lt>stevan@iinteractive.comE<gt> |
448
|
|
|
|
|
|
|
|
449
|
|
|
|
|
|
|
=head1 COPYRIGHT AND LICENSE |
450
|
|
|
|
|
|
|
|
451
|
|
|
|
|
|
|
Copyright 2007-2010 by Infinity Interactive, Inc. |
452
|
|
|
|
|
|
|
|
453
|
|
|
|
|
|
|
L<http://www.iinteractive.com> |
454
|
|
|
|
|
|
|
|
455
|
|
|
|
|
|
|
This library is free software; you can redistribute it and/or modify |
456
|
|
|
|
|
|
|
it under the same terms as Perl itself. |
457
|
|
|
|
|
|
|
|
458
|
|
|
|
|
|
|
=cut |