[pve-devel] r5694 - pve-access-control/trunk/PVE
svn-commits at proxmox.com
svn-commits at proxmox.com
Mon Mar 14 10:35:15 CET 2011
Author: dietmar
Date: 2011-03-14 10:35:15 +0100 (Mon, 14 Mar 2011)
New Revision: 5694
Modified:
pve-access-control/trunk/PVE/RPCEnvironment.pm
Log:
cleanup worker code
Modified: pve-access-control/trunk/PVE/RPCEnvironment.pm
===================================================================
--- pve-access-control/trunk/PVE/RPCEnvironment.pm 2011-03-14 09:34:30 UTC (rev 5693)
+++ pve-access-control/trunk/PVE/RPCEnvironment.pm 2011-03-14 09:35:15 UTC (rev 5694)
@@ -6,6 +6,7 @@
use IO::File;
use Fcntl qw(:flock);
use PVE::SafeSyslog;
+use PVE::Tools;
use PVE::INotify;
use PVE::Cluster;
use PVE::ProcFSTools;
@@ -267,63 +268,10 @@
return $self->{user};
}
-# UPID helper
-# WARN: $res->{filename} must not depend on PID, because we
-# use it before we know the PID
-sub upid_decode {
- my $upid = shift;
-
- my $res;
-
- # "UPID:$node:$pid:$start:$type:$data"
- if ($upid =~ m/^UPID:(\w+):(\d+)(-(\d+))?:(\d+):([^:\s]+):(.*)$/) {
- $res->{node} = $1;
- $res->{pid} = $2;
- $res->{pstart} = $4 || 0;
- $res->{starttime} = $5;
- $res->{type} = $6;
- $res->{data} = $7;
-
- if ($res->{type} eq 'vmops') {
- if ($res->{data} =~ m/^([^:\s]+):(\d+):(\S+)$/) {
- $res->{command} = $1;
- $res->{veid} = $2;
- $res->{user} = $3;
-
- $res->{filename} = "/tmp/vmops-$res->{veid}.out";
- } else {
- return undef;
- }
- } elsif ($res->{type} eq 'apldownload') {
- if ($res->{data} =~ m/^([^:\s]+):(.+)$/) {
- $res->{user} = $1;
- $res->{apl} = $2;
- $res->{filename} = "/tmp/apldownload-$res->{user}.out";
- } else {
- return undef;
- }
- }
- }
-
- return $res;
-}
-
-sub upid_encode {
- my $uip_hash = shift;
-
- my $d = $uip_hash; # shortcut
-
- return "UPID:$d->{node}:$d->{pid}-$d->{pstart}:$d->{starttime}:$d->{type}:$d->{data}";
-}
-
# start long running workers
-# $data append to the returned uniquely identifier, which
-# has the following format: "UPID:$node:$pid-$pstart:$startime:$dtype:$data"
# STDIN is redirected to /dev/null
# STDOUT,STDERR are redirected to the filename returned by upid_decode
-# that file is locked wit flock to make sure only one process
-# is writing it
sub fork_worker {
my ($self, $dtype, $data, $function) = @_;
@@ -338,36 +286,18 @@
my $node = $self->{nodename};
- # detect filename with faked PID
- my $tmp = upid_decode ("UPID:$node:0-0:0:$dtype:$data");
- my $filename = $tmp->{filename};
+ my $cpid = fork();
+ die "unable to fork worker - $!" if !defined($cpid);
- my $lockfh;
- # lock output file
- if ($filename) {
+ my $workerpuid = $cpid ? $cpid : $$;
- $lockfh = IO::File->new ($filename, O_WRONLY|O_CREAT) ||
- die "unable to open output file - $!\n";
+ my $pstart = PVE::ProcFSTools::read_proc_starttime($workerpuid) ||
+ die "unable to read process start time";
- my $wwwid = getpwnam('www-data');
- chown $wwwid, $filename;
+ my $upid = PVE::Tools::upid_encode ({
+ node => $node, pid => $workerpuid, pstart => $pstart,
+ starttime => $starttime, type => $dtype, data => $data });
- if (!flock ($lockfh, LOCK_EX|LOCK_NB)) {
- undef $lockfh; # close
- die "unable to lock output file\n";
- }
-
- if (!truncate ($lockfh, 0)) {
- die "unable to truncate output file - $!\n";
- }
- }
-
- my $cpid = fork();
- if (!defined($cpid)) {
- undef $lockfh; # close
- die "unable to fork worker - $!";
- }
-
if ($cpid == 0) {
$SIG{INT} = $SIG{QUIT} = $SIG{TERM} = sub { die "received interrupt\n"; };
@@ -380,67 +310,69 @@
POSIX::close ($psync[0]);
- PVE::INotify::inotify_close();
+ my $outfh;
- if (my $atfork = $self->{atfork}) {
- &$atfork();
- }
+ eval {
+ PVE::INotify::inotify_close();
- # same algorythm as used inside SA
+ if (my $atfork = $self->{atfork}) {
+ &$atfork();
+ }
- # STDIN = /dev/null
- my $fd = fileno (STDIN);
- close STDIN;
- POSIX::close(0) if $fd != 0;
+ # same algorythm as used inside SA
- if (!open (STDIN, "</dev/null")) {
- POSIX::_exit (1);
- kill ('KILL', $$);
- }
+ # STDIN = /dev/null
+ my $fd = fileno (STDIN);
+ close STDIN;
+ POSIX::close(0) if $fd != 0;
- # redirect STDOUT
- $fd = fileno(STDOUT);
- close STDOUT;
- POSIX::close (1) if $fd != 1;
+ die "unable to redirect STDIN - $!"
+ if !open(STDIN, "</dev/null");
- if ($filename) {
- if (!open (STDOUT, ">&", $lockfh)) {
- POSIX::_exit (1);
- kill ('KILL', $$);
- }
+ # redirect STDOUT
+ $fd = fileno(STDOUT);
+ close STDOUT;
+ POSIX::close (1) if $fd != 1;
+ my $tmp = PVE::Tools::upid_decode($upid);
+ my $filename = $tmp->{filename};
+
+ $outfh = IO::File->new ($filename, O_WRONLY|O_CREAT|O_EXCL) ||
+ die "unable to open output file - $!\n";
+
+ my $wwwid = getpwnam('www-data');
+ chown $wwwid, $outfh;
+
+ die "unable to redirect STDOUT - $!"
+ if !open(STDOUT, ">&", $outfh);
+
STDOUT->autoflush (1);
- } else {
- if (!open (STDOUT, ">/dev/null")) {
- POSIX::_exit (1);
- kill ('KILL', $$);
- }
- }
- # redirect STDERR to STDOUT
- $fd = fileno (STDERR);
- close STDERR;
- POSIX::close(2) if $fd != 2;
+ # redirect STDERR to STDOUT
+ $fd = fileno (STDERR);
+ close STDERR;
+ POSIX::close(2) if $fd != 2;
- if (!open (STDERR, ">&1")) {
- POSIX::_exit (1);
- kill ('KILL', $$);
+ die "unable to redirect STDERR - $!"
+ if !open(STDERR, ">&1");
+
+ STDERR->autoflush(1);
+ };
+ if (my $err = $@) {
+ my $msg = "ERROR: $err";
+ print STDERR "$msg\n";
+ STDERR->flush();
+ POSIX::write($psync[1], $msg, length ($msg));
+ POSIX::close($psync[1]);
+ POSIX::_exit(1);
+ kill('KILL', $$);
}
-
- STDERR->autoflush (1);
- my $pstart = PVE::ProcFSTools::read_proc_starttime ($$) ||
- die "unable to read process starttime";
-
- my $upid = upid_encode ({
- node => $node, pid => $$, pstart => $pstart,
- starttime => $starttime, type => $dtype, data => $data });
-
# sync with parent
- POSIX::write ($psync[1], $upid, length ($upid));
- POSIX::close ($psync[1]);
+ POSIX::write($psync[1], $upid, length ($upid));
+ POSIX::close($psync[1]);
- eval { &$function ($upid); };
+ eval { &$function($upid); };
my $err = $@;
if ($err) {
my $msg = "worker function failed: $err";
@@ -450,28 +382,28 @@
} else {
POSIX::_exit (0);
}
- kill ('KILL', $$);
- }
+ kill('KILL', $$);
+ }
POSIX::close ($psync[1]);
# sync with child (wait until child starts)
- my $upid = '';
- POSIX::read($psync[0], $upid, 4096);
+ my $readbuf = '';
+ POSIX::read($psync[0], $readbuf, 4096);
POSIX::close ($psync[0]);
- undef $lockfh; # close
-
&$register_worker($cpid);
- my $uh = upid_decode ($upid);
- if (!$uh ||
- !($uh->{node} eq $node && $uh->{pid} == $cpid &&
- $uh->{starttime} == $starttime &&
- $uh->{type} eq $dtype && $uh->{data} eq $data)) {
- die "got strange worker upid '$upid'\n";
+ die "got no worker upid - start worker failed\n" if !$readbuf;
+
+ if ($readbuf =~ m/^ERROR:\s*(.+)$/m) {
+ die "starting worker failed: $1\n";
}
+ if ($readbuf ne $upid) {
+ die "got strange worker upid ('$readbuf' != '$upid') - start worker failed\n";
+ }
+
return $upid;
}
More information about the pve-devel
mailing list