$ENV{'PATH'} = '/sbin:/bin:/usr/sbin:/usr/bin';
my $daemon_initialized = 0; # we only allow one instance
+my $daemon_sockets = [];
my $close_daemon_lock = sub {
my ($self) = @_;
return if $self->{terminate};
- my $count = 0;
- foreach my $cpid (keys %{$self->{workers}}) {
- $count++;
- }
-
+ my $count = scalar keys %{$self->{workers}};
my $need = $self->{max_workers} - $count;
return if $need <= 0;
}
};
+my $terminate_old_workers = sub {
+ my ($self) = @_;
+
+ # if list is empty kill sends no signal, so no checks needed
+ kill 15, keys %{$self->{old_workers}};
+};
+
my $terminate_server = sub {
my ($self, $allow_open_children) = @_;
$self->{terminate} = 1; # set flag to avoid worker restart
- if (!$self->{max_workers}) {
- eval { $self->shutdown(); };
- warn $@ if $@;
- return;
- }
-
eval { $self->shutdown(); };
warn $@ if $@;
- # we have workers - send TERM signal
-
- foreach my $cpid (keys %{$self->{workers}}) {
- kill(15, $cpid); # TERM childs
- }
+ return if !$self->{max_workers}; # if we have no workers we're done here
# if configured, leave children running on HUP
- return if $allow_open_children &&
- $self->{leave_children_open_on_reload};
+ return if $allow_open_children && $self->{leave_children_open_on_reload};
- # else, send TERM to old workers
- foreach my $cpid (keys %{$self->{old_workers}}) {
- kill(15, $cpid); # TERM childs
- }
+ # else send TERM to all (old and current) child workers
+ kill 15, (keys %{$self->{workers}}, keys %{$self->{old_workers}});
# nicely shutdown childs (give them max 10 seconds to shut down)
my $previous_alarm = alarm(10);
if ($restart && $self->{max_workers}) {
if (my $wpids = $ENV{PVE_DAEMON_WORKER_PIDS}) {
foreach my $pid (split(':', $wpids)) {
+ # check & untaint
if ($pid =~ m/^(\d+)$/) {
$self->{old_workers}->{$1} = 1;
}
&$old_sig_chld(@_) if $old_sig_chld;
};
- # catch worker finished during restart phase
- &$finish_workers($self);
-
# now loop forever (until we receive terminate signal)
for (;;) {
&$start_workers($self);
sleep(5);
+ &$terminate_old_workers($self);
&$finish_workers($self);
last if $self->{terminate};
}
$ENV{RESTART_PVE_DAEMON} = 1;
+ foreach my $ds (@$daemon_sockets) {
+ $ds->fcntl(Fcntl::F_SETFD(), 0);
+ }
+
if ($self->{max_workers}) {
- my @workers = keys %{$self->{workers}};
- push @workers, keys %{$self->{old_workers}};
+ my @workers = (keys %{$self->{workers}}, keys %{$self->{old_workers}});
$ENV{PVE_DAEMON_WORKER_PIDS} = join(':', @workers);
}
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) = @_;
code => sub {
my ($param) = @_;
- $self->start($param->{debug});
+ if (&$init_ppid() || $param->{debug}) {
+ $self->start($param->{debug});
+ } else {
+ PVE::Tools::run_command(['systemctl', 'start', $self->{name}]);
+ }
return undef;
}});
code => sub {
my ($param) = @_;
- &$reload_daemon($self, $use_hup);
+ if (&$init_ppid()) {
+ &$reload_daemon($self, $use_hup);
+ } else {
+ PVE::Tools::run_command(['systemctl', $use_hup ? 'reload-or-restart' : 'restart', $self->{name}]);
+ }
return undef;
}});
code => sub {
my ($param) = @_;
- $self->stop();
+ if (&$init_ppid()) {
+ $self->stop();
+ } else {
+ PVE::Tools::run_command(['systemctl', 'stop', $self->{name}]);
+ }
return undef;
}});
$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(
$ENV{"PVE_DAEMON_SOCKET_$port"} = $socket->fileno;
}
- # remove FD_CLOEXEC bit to reuse on exec
- $socket->fcntl(Fcntl::F_SETFD(), 0);
-
+ push @$daemon_sockets, $socket;
+
return $socket;
}