X-Git-Url: https://git.proxmox.com/?p=pve-common.git;a=blobdiff_plain;f=data%2FPVE%2FDaemon.pm;h=7b3992051f82407418413a09ba9820755b270ca7;hp=b6714531c7253b8e95a03b57e91547b02b37f46d;hb=d7950851db12d67dfacb361a8a11f416fb8fddc6;hpb=7db2b94082ae5241b94a9f23d526a44737014bd1 diff --git a/data/PVE/Daemon.pm b/data/PVE/Daemon.pm index b671453..7b39920 100644 --- a/data/PVE/Daemon.pm +++ b/data/PVE/Daemon.pm @@ -5,11 +5,14 @@ package PVE::Daemon; # Features: # * lock and write PID file /var/run/$name.pid to make sure onyl # one instance is running. +# * keep lock open during restart # * correctly daemonize (redirect STDIN/STDOUT) # * restart by stop/start, exec, or signal HUP # * daemon restart on error (option 'restart_on_error') # * handle worker processes (option 'max_workers') - +# * allow to restart while workers are still runningl +# (option 'leave_children_open_on_reload') + use strict; use warnings; use PVE::SafeSyslog; @@ -120,11 +123,13 @@ my $server_cleanup = sub { my $finish_workers = sub { my ($self) = @_; - foreach my $cpid (keys %{$self->{workers}}) { - my $waitpid = waitpid($cpid, WNOHANG); - if (defined($waitpid) && ($waitpid == $cpid)) { - delete ($self->{workers}->{$cpid}); - syslog('info', "worker $cpid finished"); + foreach my $id (qw(workers old_workers)) { + foreach my $cpid (keys %{$self->{$id}}) { + my $waitpid = waitpid($cpid, WNOHANG); + if (defined($waitpid) && ($waitpid == $cpid)) { + delete ($self->{$id}->{$cpid}); + syslog('info', "worker $cpid finished"); + } } } }; @@ -192,6 +197,9 @@ my $terminate_server = sub { kill(15, $cpid); # TERM childs } + return if $self->{got_hup_signal} && + $self->{leave_children_open_on_reload}; + # nicely shutdown childs (give them max 10 seconds to shut down) my $previous_alarm = alarm(10); eval { @@ -299,9 +307,9 @@ my $server_run = sub { $SIG{HUP} = sub { local ($@, $!, $?); # do not overwrite error vars syslog('info', "received signal HUP"); + $self->{got_hup_signal} = 1; if ($self->{max_workers}) { &$terminate_server($self); - $self->{got_hup_signal} = 1; } elsif ($self->can('hup')) { eval { $self->hup() }; warn $@ if $@; @@ -367,7 +375,8 @@ sub new { delete $ENV{PVE_DAEMON_LOCK_FD}; if (defined($lockfd)) { - $lockfd =~ m/^(\d+)$/; + die "unable to parse lock fd '$lockfd'\n" + if $lockfd !~ m/^(\d+)$/; $lockfd = $1; # untaint } @@ -386,6 +395,7 @@ sub new { env_restart_pve_daemon => $restart, env_pve_lock_fd => $lockfd, workers => {}, + old_workers => {}, }, $class; foreach my $opt (keys %params) { @@ -398,10 +408,22 @@ sub new { $self->{$opt} = $value; } elsif ($opt eq 'max_workers') { $self->{$opt} = $value; + } elsif ($opt eq 'leave_children_open_on_reload') { + $self->{$opt} = $value; } else { die "unknown daemon option '$opt'\n"; } } + + if ($restart && $self->{max_workers}) { + if (my $wpids = $ENV{PVE_DAEMON_WORKER_PIDS}) { + foreach my $pid (split(':', $wpids)) { + if ($pid =~ m/^(\d+)$/) { + $self->{old_workers}->{$1} = 1; + } + } + } + } $self->{pidfile} = "$self->{run_dir}/${name}.pid"; @@ -441,6 +463,12 @@ sub restart_daemon { $ENV{RESTART_PVE_DAEMON} = 1; + if ($self->{max_workers}) { + my @workers = keys %{$self->{workers}}; + push @workers, keys %{$self->{old_workers}}; + $ENV{PVE_DAEMON_WORKER_PIDS} = join(':', @workers); + } + sleep($waittime) if $waittime; # avoid high server load due to restarts PVE::INotify::inotify_close(); @@ -561,7 +589,9 @@ sub stop { } sub register_start_command { - my ($self, $class, $description) = @_; + my ($self, $description) = @_; + + my $class = ref($self); $class->register_method({ name => 'start', @@ -612,7 +642,9 @@ my $reload_daemon = sub { }; sub register_restart_command { - my ($self, $class, $use_hup, $description) = @_; + my ($self, $use_hup, $description) = @_; + + my $class = ref($self); $class->register_method({ name => 'restart', @@ -635,7 +667,9 @@ sub register_restart_command { } sub register_reload_command { - my ($self, $class, $description) = @_; + my ($self, $description) = @_; + + my $class = ref($self); $class->register_method({ name => 'reload', @@ -658,7 +692,9 @@ sub register_reload_command { } sub register_stop_command { - my ($self, $class, $description) = @_; + my ($self, $description) = @_; + + my $class = ref($self); $class->register_method({ name => 'stop', @@ -681,7 +717,9 @@ sub register_stop_command { } sub register_status_command { - my ($self, $class, $description) = @_; + my ($self, $description) = @_; + + my $class = ref($self); $class->register_method({ name => 'status',