# * allow to restart while workers are still runningl
# (option 'leave_children_open_on_reload')
# * run as different user using setuid/setgid
-
+
use strict;
use warnings;
use English;
for my $sig (qw(CHLD HUP INT TERM QUIT)) {
$SIG{$sig} = 'DEFAULT'; # restore default handler
- # AnyEvent signals only works if $SIG{XX} is
+ # AnyEvent signals only works if $SIG{XX} is
# undefined (perl event loop)
delete $SIG{$sig}; # so that we can handle events with AnyEvent
}
if (my $fd = $self->{env_pve_lock_fd}) {
$self->{daemon_lock_fh} = IO::Handle->new_from_fd($fd, "a");
-
+
} else {
$waittime = 5;
my $pidfile = $self->{pidfile};
- die "can't open pid file '$pidfile' - $!\n" if !open (PIDFH, ">$pidfile");
+ open (my $PID_FH, '>', "$pidfile") or die "can't open pid file '$pidfile' - $!\n";
- print PIDFH "$$\n";
- close (PIDFH);
+ print $PID_FH "$$\n";
+ close ($PID_FH);
};
my $server_cleanup = sub {
initlog($self->{name});
- my $restart = $ENV{RESTART_PVE_DAEMON};
- delete $ENV{RESTART_PVE_DAEMON};
+ my $restart = delete $ENV{RESTART_PVE_DAEMON};
$self->{env_restart_pve_daemon} = $restart;
my $lockfd = $ENV{PVE_DAEMON_LOCK_FD};
$self->init();
if (!$debug) {
- open STDIN, '</dev/null' || die "can't read /dev/null";
- open STDOUT, '>/dev/null' || die "can't write /dev/null";
+ open STDIN, '<', '/dev/null' or die "can't read /dev/null - $!";
+ open STDOUT, '>', '/dev/null' or die "can't write /dev/null - $!";
}
if (!$self->{env_restart_pve_daemon} && !$debug) {
syslog('info' , "starting server");
}
- POSIX::setsid();
+ POSIX::setsid();
open STDERR, '>&STDOUT' || die "can't close STDERR\n";
}
};
- eval {
+ eval {
if ($self->{max_workers}) {
my $old_sig_chld = $SIG{CHLD};
local $SIG{CHLD} = sub {
};
# now loop forever (until we receive terminate signal)
- for (;;) {
+ for (;;) {
&$start_workers($self);
sleep(5);
&$terminate_old_workers($self);
} else {
$self->run();
- }
+ }
};
my $err = $@;
eval {
my $class = ref($this) || $this;
- $self = bless {
+ $self = bless {
name => $name,
pidfile => "/var/run/${name}.pid",
workers => {},
die "unknown daemon option '$opt'\n";
}
}
-
+
# untaint
$self->{cmdline} = [map { /^(.*)$/ } @$cmdline];
return 0 if !$pid_str;
return 0 if $pid_str !~ m/^(\d+)$/; # untaint
-
+
my $pid = int($1);
return $pid;
# checks if the process was started by systemd
my $init_ppid = sub {
-
if (getppid() == 1) {
return 1;
} else {
return 0;
}
-};
+};
sub running {
my ($self) = @_;
}
return undef;
- }});
+ }});
}
my $reload_daemon = sub {
if ($self->{env_restart_pve_daemon}) {
$self->start();
} else {
- my ($running, $pid) = $self->running();
+ my ($running, $pid) = $self->running();
if (!$running) {
$self->start();
} else {
}
return undef;
- }});
+ }});
}
sub register_reload_command {
&$reload_daemon($self, 1);
return undef;
- }});
+ }});
}
sub register_stop_command {
code => sub {
my ($param) = @_;
-
+
if (&$init_ppid()) {
$self->stop();
} else {
}
return undef;
- }});
+ }});
}
sub register_status_command {
additionalProperties => 0,
properties => {},
},
- returns => {
+ returns => {
type => 'string',
enum => ['stopped', 'running'],
},
# some useful helper
sub create_reusable_socket {
- my ($self, $port, $host, $family) = @_;
+ my ($self, $port, $host) = @_;
die "no port specifed" if !$port;
if (defined($sockfd = $ENV{"PVE_DAEMON_SOCKET_$port"}) &&
$self->{env_restart_pve_daemon}) {
- die "unable to parse socket fd '$sockfd'\n"
+ die "unable to parse socket fd '$sockfd'\n"
if $sockfd !~ m/^(\d+)$/;
$sockfd = $1; # untaint
$socket = IO::Socket::IP->new;
- $socket->fdopen($sockfd, 'w') ||
+ $socket->fdopen($sockfd, 'w') ||
die "cannot fdopen file descriptor '$sockfd' - $!\n";
$socket->fcntl(Fcntl::F_SETFD(), Fcntl::FD_CLOEXEC);
} else {
- $socket = IO::Socket::IP->new(
- LocalAddr => $host,
+ my %sockargs = (
LocalPort => $port,
Listen => SOMAXCONN,
- Family => $family,
Proto => 'tcp',
GetAddrInfoFlags => 0,
- ReuseAddr => 1) ||
- die "unable to create socket - $@\n";
+ ReuseAddr => 1,
+ );
+ if (defined($host)) {
+ $socket = IO::Socket::IP->new( LocalHost => $host, %sockargs) ||
+ die "unable to create socket - $@\n";
+ } else {
+ # disabling AF_INET6 (by adding ipv6.disable=1 to the kernel cmdline)
+ # causes bind on :: to fail, try 0.0.0.0 in that case
+ $socket = IO::Socket::IP->new( LocalHost => '::', %sockargs) //
+ IO::Socket::IP->new( LocalHost => '0.0.0.0', %sockargs);
+ die "unable to create socket - $@\n" if !$socket;
+ }
# we often observe delays when using Nagle algorithm,
# so we disable that to maximize performance