use vars qw($VERSION @ISA @EXPORT_OK %EXPORT_TAGS $Q $SIG_CODEREF);
BEGIN {
- $VERSION = '0.19';
+ $VERSION = '0.28';
+ $VERSION = eval $VERSION;
@ISA = qw(Exporter);
@EXPORT_OK = qw(pm_manage pm_die pm_wait
pm_write_pid_file pm_remove_pid_file
FCGI::ProcManager uses POSIX::sigaction() to override the default SA_RESTART
policy used for perl's %SIG behavior. Specifically, the process manager
never uses SA_RESTART, while the child FastCGI servers turn off SA_RESTART
-around the accept(2) loop, but re-enstate it otherwise.
+around the accept(2) loop, but reinstate it otherwise.
The desired (and implemented) effect is to give a request as big a chance as
possible to succeed and to delay their exits until after their request,
$this->{PIDS} = {};
# initialize signal constructions.
- unless ($this->no_signals()) {
+ unless ($this->no_signals() or $^O eq 'MSWin32') {
$this->{sigaction_no_sa_restart} =
POSIX::SigAction->new('FCGI::ProcManager::sig_sub');
$this->{sigaction_sa_restart} =
return $this;
}
+sub _set_signal_handler {
+ my ($this, $signal, $restart) = @_;
+
+ if ($^O eq 'MSWin32') {
+ $SIG{$signal} = 'FCGI::ProcManager::sig_sub';
+ } else {
+ no strict 'refs';
+ sigaction(&{"POSIX::SIG$signal"}(), $restart ? $this->{sigaction_sa_restart} : $this->{sigaction_no_sa_restart})
+ or $this->pm_warn("sigaction: SIG$signal: $!");
+ }
+}
+
=head1 Manager methods
=head2 pm_manage
my ($this,%values) = self_or_default(@_);
map { $this->pm_parameter($_,$values{$_}) } keys %values;
+ local $SIG{CHLD}; # Replace the SIGCHLD default handler in case
+ # somebody shit on it whilst loading code.
+
# skip to handling now if we won't be managing any processes.
$this->n_processes() or return;
last MANAGING_LOOP;
}
- for (my $s = $this->start_delay(); $s; $s = sleep $s) {};
+ for (my $s = $this->start_delay(); $s > 0; $s -= sleep $s) {};
}
# this should block until the next server dies.
# We do NOT want SA_RESTART in the process manager.
# -- we want start the shutdown sequence immediately upon SIGTERM.
unless ($this->no_signals()) {
- sigaction(SIGTERM, $this->{sigaction_no_sa_restart}) or
- $this->pm_warn("sigaction: SIGTERM: $!");
- sigaction(SIGHUP, $this->{sigaction_no_sa_restart}) or
- $this->pm_warn("sigaction: SIGHUP: $!");
+ $this->_set_signal_handler('TERM', 0);
+ $this->_set_signal_handler('HUP', 0);
$SIG_CODEREF = sub { $this->sig_manager(@_) };
}
my ($this) = self_or_default(@_);
# wait for the next server to die.
- next if (my $pid = wait()) < 0;
+ return if ((my $pid = wait()) < 0);
# notify when one of our servers have died.
delete $this->{PIDS}->{$pid} and
sub pm_write_pid_file {
my ($this,$fname) = self_or_default(@_);
$fname ||= $this->pid_fname() or return;
- if (!open PIDFILE, ">$fname") {
+ my $PIDFILE;
+ if (!open $PIDFILE, ">$fname") {
$this->pm_warn("open: $fname: $!");
return;
}
- print PIDFILE "$$\n";
- close PIDFILE;
+ print $PIDFILE "$$\n" or die "Could not print PID: $!";
+ close $PIDFILE or die "Could not close PID file: $!";
}
=head2 pm_remove_pid_file
# begin to handle signals.
# We'll want accept(2) to return -1(EINTR) on caught signal..
unless ($this->no_signals()) {
- sigaction(SIGTERM, $this->{sigaction_no_sa_restart}) or $this->pm_warn("sigaction: SIGTERM: $!");
- sigaction(SIGHUP, $this->{sigaction_no_sa_restart}) or $this->pm_warn("sigaction: SIGHUP: $!");
+ $this->_set_signal_handler('TERM', 0);
+ $this->_set_signal_handler('HUP', 0);
$SIG_CODEREF = sub { $this->sig_handler(@_) };
}
# change the name of this process as it appears in ps(1) output.
$this->pm_change_process_name("perl-fcgi");
+
+ # Re-srand in case someone called rand before the fork, so that
+ # children get different random numbers.
+ srand;
}
=head2 pm_pre_dispatch
# Now, we want the request to continue unhindered..
unless ($this->no_signals()) {
- sigaction(SIGTERM, $this->{sigaction_sa_restart}) or $this->pm_warn("sigaction: SIGTERM: $!");
- sigaction(SIGHUP, $this->{sigaction_sa_restart}) or $this->pm_warn("sigaction: SIGHUP: $!");
+ $this->_set_signal_handler('TERM', 1);
+ $this->_set_signal_handler('HUP', 1);
}
}
}
# We'll want accept(2) to return -1(EINTR) on caught signal..
unless ($this->no_signals()) {
- sigaction(SIGTERM, $this->{sigaction_no_sa_restart}) or $this->pm_warn("sigaction: SIGTERM: $!");
- sigaction(SIGHUP, $this->{sigaction_no_sa_restart}) or $this->pm_warn("sigaction: SIGHUP: $!");
+ $this->_set_signal_handler('TERM', 0);
+ $this->_set_signal_handler('HUP', 0);
}
}