]>
git.proxmox.com Git - pve-manager-legacy.git/blob - PVE/APIDaemon.pm
1 package PVE
::APIDaemon
;
5 use POSIX
":sys_wait_h";
6 use Socket
qw(IPPROTO_TCP TCP_NODELAY SOMAXCONN);
15 my ($this, %args) = @_;
17 my $class = ref($this) || $this;
19 die "no lockfile" if !$args{lockfile
};
21 my $lockfh = IO
::File-
>new(">>$args{lockfile}") ||
22 die "unable to open lock file '$args{lockfile}' - $!\n";
24 my $socket = IO
::Socket
::INET-
>new(
25 LocalAddr
=> $args{host
} || undef,
26 LocalPort
=> $args{port
} || 80,
30 die "unable to create socket - $@\n";
32 # we ofter observe delays when using Nagle algorithm,
33 # so we disable that to maximize performance
34 setsockopt($socket, IPPROTO_TCP
, TCP_NODELAY
, 1);
37 my $self = bless { cfg
=> $cfg }, $class;
39 $cfg->{socket} = $socket;
40 $cfg->{lockfh
} = $lockfh;
41 $cfg->{max_workers
} = 3 if !$cfg->{max_workers
};
42 $cfg->{trusted_env
} = 0 if !defined($cfg->{trusted_env
});
50 syslog
('info', "worker $cpid finished");
55 foreach my $cpid (keys %$workers) {
56 my $waitpid = waitpid ($cpid, WNOHANG
);
57 if (defined($waitpid) && ($waitpid == $cpid)) {
58 delete ($workers->{$cpid});
59 worker_finished
($cpid);
65 foreach my $cpid (keys %$workers) {
66 if (!kill(0, $cpid)) {
67 waitpid($cpid, POSIX
::WNOHANG
());
68 delete $workers->{$cpid};
69 worker_finished
($cpid);
78 foreach my $cpid (keys %$workers) {
82 my $need = $self->{cfg
}->{max_workers
} - $count;
86 syslog
('info', "starting $need worker(s)");
91 if (!defined ($pid)) {
92 syslog
('err', "can't fork worker");
94 } elsif ($pid) { #parent
96 syslog
('info', "worker $pid started");
101 $SIG{TERM
} = $SIG{QUIT
} = 'DEFAULT'; # we handle that with AnyEvent
104 my $server = PVE
::HTTPServer-
>new(%{$self->{cfg
}});
109 sleep(5); # avoid fast restarts
116 sub terminate_server
{
118 syslog
('info', "received terminate request");
120 foreach my $cpid (keys %$workers) {
121 kill (15, $cpid); # TERM childs
124 # nicely shutdown childs (give them max 10 seconds to shut down)
125 my $previous_alarm = alarm (10);
127 local $SIG{ALRM
} = sub { die "timeout\n" };
129 while ((my $pid = waitpid (-1, 0)) > 0) {
130 if (defined($workers->{$pid})) {
131 delete ($workers->{$pid});
132 worker_finished
($pid);
135 alarm(0); # avoid race condition
139 alarm ($previous_alarm);
142 syslog
('err', "error stopping workers (will kill them now) - $err");
143 foreach my $cpid (keys %$workers) {
144 # KILL childs still alive!
145 if (kill (0, $cpid)) {
146 delete ($workers->{$cpid});
147 syslog
("err", "kill worker $cpid");
158 my $old_sig_chld = $SIG{CHLD
};
159 local $SIG{CHLD
} = sub {
161 &$old_sig_chld(@_) if $old_sig_chld;
164 my $old_sig_term = $SIG{TERM
};
165 local $SIG{TERM
} = sub {
167 &$old_sig_term(@_) if $old_sig_term;
169 local $SIG{QUIT
} = sub {
171 &$old_sig_term(@_) if $old_sig_term;
174 local $SIG{HUP
} = sub {
175 syslog
("info", "received reload request");
176 foreach my $cpid (keys %$workers) {
177 kill (15, $cpid); # kill childs
182 $self->start_workers();
184 $self->test_workers();
190 syslog
('err', "ERROR: $err");