-xCATd portion of solution to sourceforge bug 1822784, plugin instances now receive SIGINT and things shut down. Plugins with children still have to manage exit intelligently, but the same is true for standalone programs to begin with, so shouldn't be harder on developer than that

git-svn-id: https://svn.code.sf.net/p/xcat/code/xcat-core/trunk@1132 8638fb3e-16cb-4fca-ae20-7b5d299a9bcd
This commit is contained in:
jbjohnso 2008-04-21 15:27:11 +00:00
parent 4c40cb6b25
commit c6edb78635

View File

@ -11,6 +11,7 @@ use File::Path;
use Time::HiRes qw(sleep);
use Thread qw(yield);
use xCAT::Client submit_request;
my $clientselect = new IO::Select;
use IO::Socket::SSL;
my $inet6support;
@ -378,8 +379,8 @@ $SIG{CHLD} = sub { while (waitpid(-1,WNOHANG) > 0) {} };
$SIG{TERM} = $SIG{INT} = sub {
printf("Asked to quit...\n");
$quit++;
$SIG{ALRM} = sub { die "Did not close out in time for 5 second grace period"; };
alarm(5);
$SIG{ALRM} = sub { exit 0; }; #die "Did not close out in time for 5 second grace period"; };
alarm(2);
};
my $pid = xCAT::Utils->xfork;
@ -405,7 +406,7 @@ my $listener = IO::Socket::INET->new(
);
unless ($listener) {
kill $pid;
kill 2, $pid;
syslog("err","xCAT service unable to open SSL services on $port: $!");
closelog();
die "ERROR:Unable to start xCAT service on port $port.";
@ -452,6 +453,7 @@ until ($quit) {
unless ($connection) {
exit 0;
}
$clientselect->add($connection);
my $peerhost=undef;
my $peer=$connection->peer_certificate("owner");
if ($peer) {
@ -664,7 +666,7 @@ sub plugin_command {
}
unless ($sock) { return $Main::resps };
#while ($children > 0) {
while ($check_fds->count > 0) { #this tracks end of useful data from children much more closely
while (($children > 0) and ($check_fds->count > 0)) { #this tracks end of useful data from children much more closely
relay_fds($check_fds,$sock);
}
#while (relay_fds($check_fds,$sock)) {}
@ -677,6 +679,7 @@ sub plugin_command {
}
my $dispatch_dnf=0;
my %dispatched_children;
my $dispatch_cb;
my $dispatch_parentfd;
sub dispatch_callback {
@ -695,8 +698,16 @@ sub dispatch_callback {
yield; #This has to happen before next line could possibly work anyway
my $parselect = new IO::Select;
$parselect->add($dispatch_parentfd);
$parselect->can_read(10); #block for up to 10 seconds before continuing
#<$dispatch_parentfd>; #Block until parent acks data
my $rsp;
if ($parselect->can_read(5)) { #block for up to 5 seconds before continuing
if ($rsp = <$dispatch_parentfd>) {
if ($rsp =~ /die/) {
exit 0;
}
} else {
$parselect->remove($dispatch_parentfd); #Block until parent acks data
}
}
}
}
@ -710,13 +721,40 @@ sub relay_dispatch {
$data .= <$rin>;
}
my $response = thaw($data);
print $rin "fin\n";
print $rin "dfin\n";
$dispatch_cb->($response);
} else {
$fds->remove($rin);
close($rin);
}
}
foreach my $rin ($clientselect->can_read(0)) {
my $subselect = new IO::Select;
$subselect->add($rin);
my $clientintr="";
my $subdata;
while ($subselect->can_read(1)) {
if ($subdata=<$rin>) {
$clientintr.=$subdata;
} else {
$subselect->remove($rin);
close($rin);
}
}
$clientintr=XMLin($clientintr, SuppressEmpty=>undef,ForceArray=>1 );
if ($clientintr->{abortcommand}->[0]) {
foreach my $cin ($fds->handles) {
foreach (keys %dispatched_children) {
kill 2, $_;
}
print $cin "die\n";
$fds->remove($cin);
close($cin);
}
die "Client abort requested";
}
}
yield; #At this point, explicitly yield to other processes. If children will have more data, this process would otherwise uselessly loop on data that never will be. If children are all done, still no harm in waiting a short bit for a timeslice to come back
return scalar(@ready_ins);
}
@ -746,7 +784,7 @@ sub dispatch_request {
}
my $childrn=0;
$SIG{CHLD} = sub {while (waitpid(-1, WNOHANG) > 0) { $childrn--; } };
$SIG{CHLD} = sub {my $cpid; while ($cpid =waitpid(-1, WNOHANG) > 0) { undef $dispatched_children{$cpid}; $childrn--; } };
foreach (@{$reqs}) {
my $pfd;
my $parfd; #use a private variable so it won't trounce itself recursively
@ -757,6 +795,7 @@ sub dispatch_request {
$pfd->autoflush(1);
$child = xCAT::Utils->xfork;
if ($child) {
$dispatched_children{$child}=1;
$child_fdset->add($pfd);
$childrn++;
next;
@ -764,9 +803,10 @@ sub dispatch_request {
unless (defined $child) {
$dispatch_cb->({error=>['Fork failure dispatching request'],errorcode=>[1]});
}
$dispatch_parentfd = $parfd;
$dispatch_parentfd = $parfd;
if ($_->{'_xcatdest'} and thishostisnot($_->{'_xcatdest'})) {
$ENV{XCATHOST} = ( $_->{'_xcatdest'} =~ /:/ ? $_->{'_xcatdest'} : $_->{'_xcatdest'}.":3001" );
$$progname.=": connection to ".$ENV{XCATHOST};
eval {
undef $_->{'_xcatdest'};
xCAT::Client::submit_request($_,\&dispatch_callback,$xcatdir."/cert/server-key.pem",$xcatdir."/cert/server-cert.pem",$xcatdir."/cert/ca.pem");
@ -776,13 +816,14 @@ sub dispatch_request {
syslog("local4|err","Error dispatching request: ".$@);
}
} else {
$$progname.=": locally executing";
undef $SIG{CHLD};
${"xCAT_plugin::".$modname."::"}{process_request}->($_,\&dispatch_callback,\&do_request);
}
exit;
}
#while ($childrn > 0) { relay_dispatch($child_fdset) }
while ($child_fdset->count > 0) { relay_dispatch($child_fdset) }
while (($childrn > 0) and ($child_fdset->count > 0)) { relay_dispatch($child_fdset) }
while (relay_dispatch($child_fdset)) { } #Potentially useless drain.
}
@ -859,7 +900,12 @@ sub convey_response {
return;
}
print $parent_fd XMLout($resp,KeyAttr=>[], NoAttr=>1,RootName=>'xcatresponse');
<$parent_fd>; #Block until parent acks data
my $parsel = new IO::Select;
$parsel->add($parent_fd);
if ($parsel->can_read(5)) { #block up to five seconds for parent to ack
<parent_fd>;
}
#<$parent_fd>; #Block until parent acks data
# KeyAttr => [], NoAttr => 1)
}
@ -953,11 +999,12 @@ sub service_connection {
syslog("local4|info","xcatd: Unexpected client disconnect");
}
}
alarm(0);
$SIG{ALRM}= sub { die "Failure shutting down" };
alarm(5);
foreach (keys %tables) {
$tables{$_}->commit;
}
$sock->close;
$sock->close(SSL_fast_shutdown=>1);
if ($timedout == 1) {
printf ("Client timeout");
}
@ -981,7 +1028,7 @@ sub relay_fds { #Relays file descriptors from pipes to children to the SSL socke
}
}
if ($line) {
print $rfh "fin\n"; #Notify convey_response message done
print $rfh "nfin\n"; #Notify convey_response message done
} else {
$fds->remove($rfh);
close($rfh);