App-Base
view release on metacpan or search on metacpan
lib/App/Base/Daemon.pm view on Meta::CPAN
die("Couldn't lock " . $self->pid_file . ". Is another copy of this daemon already running?");
}
}
}
$SIG{PIPE} = 'IGNORE'; ## no critic (RequireLocalizedPunctuationVars)
foreach my $signal (@{$self->shutdown_signals}) {
$SIG{$signal} = sub { App::Base::Daemon::_signal_shutdown($self, @_) }; ## no critic (RequireLocalizedPunctuationVars)
}
# Daemonize unless specifically asked not to.
unless ($self->getOption('no-fork') or $hot_reload) {
my $child_pid = fork();
if (!defined($child_pid)) {
die("Can't fork child process: $!");
} elsif ($child_pid == 0) {
POSIX::setsid();
my $grandchild_pid = fork();
if (!defined($grandchild_pid)) {
die("Can't fork grandchild process: $!");
} elsif ($grandchild_pid != 0) {
$pid->close if $pid;
exit 0;
} else {
# close all STD* files, and redirect STD* to /dev/null
for (0 .. 2) {
POSIX::close($_) unless $pid and $_ == $pid->fileno;
}
(open(STDIN, '<', '/dev/null') and open(STDOUT, '>', '/dev/null') and open(STDERR, '>', '/dev/null'))
or die "Couldn't open /dev/null: $!";
}
} else {
waitpid($child_pid, 0);
$pid->close if $pid;
return $?;
}
}
$self->_set_user_and_group unless $hot_reload;
$pid->write_pid if $pid;
my $result;
try { $result = $self->daemon_run(@{$self->parsed_args}); }
catch ($e) {
$self->error($e);
}
undef $pid;
return $result;
}
sub _set_user_and_group {
my $self = shift;
my $user = $self->getOption('user') // $self->user;
my $group = $self->getOption('group') // $self->group;
if ($user or $group) {
if ($> == 0) {
my ($uid, $gid) = (0, 0);
if ($group) {
$gid = getgrnam($group) or $self->error("Can't find group $group");
}
if ($user) {
$uid = getpwnam($user) or $self->error("Can't find user $user");
}
if ($uid or $gid) {
chown $uid, $gid, $self->pid_file;
}
if ($gid) {
POSIX::setgid($gid);
}
if ($uid) {
POSIX::setuid($uid);
}
} else {
warn("Not running as root, can't setuid/setgid") unless $self->getOption('no-warn');
}
}
return;
}
=head2 error
Handles the output of errors, including shutting down the running daemon by
calling handle_shutdown(). If you have a serious problem that should NOT
result in shutting down your daemon, use warn() instead.
=cut
sub error { ## no critic (RequireArgUnpacking)
my $self = shift;
warn("Shutting down: " . join(' ', @_)) unless $self->getOption('no-warn');
$self->handle_shutdown();
return exit(-1);
}
no Moose::Role;
1;
__END__
=head1 USAGE
=head2 Inheritance
Invocation of a App::Base::Daemon-based daemon is accomplished as follows:
=over 4
=item -
Define a class that implements App::Base::Daemon
=item -
Instantiate an object of that class via new()
=item -
Run the daemon by calling run(). The return value of run() is the exit
status of the daemon, and should typically be passed back to the calling
program via exit()
=back
=head2 The new() method
(See App::Base::Script::Common::new)
=head2 Options handling
(See App::Base::Script::Common, "Options handling")
=head1 LICENSE AND COPYRIGHT
( run in 2.159 seconds using v1.01-cache-2.11-cpan-ceb78f64989 )