App-Sv
view release on metacpan or search on metacpan
lib/App/Sv.pm view on Meta::CPAN
return bless { run => $run, conf => $conf->{global} }, $class;
}
# Start everything
sub run {
my $self = shift;
my $cv = AE::cv;
# signal watchers
my $int_s = AE::signal 'INT' => sub {
$self->_signal_all_svc('INT', $cv);
};
my $hup_s = AE::signal 'HUP' => sub {
$self->_signal_all_svc('HUP', $cv);
};
my $term_s = AE::signal 'TERM' => sub {
$self->_signal_all_svc('TERM');
$cv->send
};
# set global umask
umask oct($self->{conf}->{umask}) if $self->{conf}->{umask};
# initialize logger
$self->{log} = App::Sv::Log->new($self->{conf}->{log});
# open controling socket; load commands
$self->_listener() if $self->{conf}->{listen};
$self->{cmds} = $self->_client_cmds() if ref $self->{server} eq 'Guard';
# start all services
foreach my $key (keys %{ $self->{run} }) {
my $svc = $self->{run}->{$key};
$self->_start_svc($svc);
}
$cv->recv;
}
sub _start_svc {
my ($self, $svc) = @_;
my $debug = $self->{log}->logger(8);
my $warn = $self->{log}->logger(5);
$svc->{state} = 'start';
if ($svc->{start_count}) {
$svc->{start_count}++;
}
else {
$svc->{start_count} = 1;
}
$debug->("Starting '$svc->{name}' attempt $svc->{start_count}");
my $pid = fork();
if (!defined $pid) {
$warn->("Failed to fork '$svc->{name}': $!");
$self->_restart_svc($svc);
return;
}
if ($pid == 0) {
# child
# set egid/euid
if ($svc->{group}) {
$svc->{gid} = getgrnam($svc->{group});
$) = $svc->{gid};
}
if ($svc->{user}) {
$svc->{uid} = getpwnam($svc->{user});
$> = $svc->{uid};
}
# set process umask
umask oct($svc->{umask}) if $svc->{umask};
# change working directory
if ($svc->{cwd}) {
chdir $svc->{cwd}
or $warn->("Failed cwd for '$svc->{name}': $!");
}
# set environment
%ENV = %{$svc->{env}} if $svc->{env} && ref $svc->{env} eq 'HASH';
# set session id
if ($svc->{setsid}) {
$svc->{pgrp} = POSIX::setsid()
or $warn->("Failed setsid for '$svc->{name}': $!");
};
# start process
if ($svc->{cmd} && !ref $svc->{cmd}) {
$debug->("Executing command '$svc->{name}'");
exec($svc->{cmd});
}
elsif ($svc->{cmd} && ref $svc->{cmd} eq 'ARRAY') {
$debug->("Executing command '$svc->{name}'");
exec(@{$svc->{cmd}});
}
elsif ($svc->{code} && ref $svc->{code} eq 'CODE') {
$debug->("Executing code '$svc->{name}'");
$svc->{code}->();
}
elsif ($svc->{code} && ref $svc->{code} eq 'ARRAY') {
my $code = shift @{$svc->{code}};
if (ref $code eq 'CODE') {
$debug->("Executing code '$svc->{name}'");
$code->(@{$svc->{code}});
}
}
POSIX::_exit(1);
}
else {
# parent
$debug->("Watching pid $pid for '$svc->{name}'");
$svc->{pid} = $pid;
$svc->{watcher} = AE::child $pid, sub {
$self->_child_exited($svc, @_);
};
$svc->{start_ts} = time;
my $t; $t = AE::timer $svc->{start_wait}, 0, sub {
$self->_check_svc_up($svc);
undef $t;
};
}
return $pid;
}
sub _child_exited {
my ($self, $svc, undef, $status) = @_;
( run in 1.150 second using v1.01-cache-2.11-cpan-ceb78f64989 )