version 1.17, 2001/08/30 20:02:28
|
version 1.20, 2001/11/27 23:11:42
|
Line 16
|
Line 16
|
# 12/05 Scott Harrison |
# 12/05 Scott Harrison |
# 12/05 Gerd Kortemeyer |
# 12/05 Gerd Kortemeyer |
# 01/10/01 Scott Harrison |
# 01/10/01 Scott Harrison |
# 03/14/01,03/15,06/12 Gerd Kortemeyer |
# 03/14/01,03/15,06/12,11/26,11/27 Gerd Kortemeyer |
# |
# |
# based on nonforker from Perl Cookbook |
# based on nonforker from Perl Cookbook |
# - server who multiplexes without forking |
# - server who multiplexes without forking |
Line 30 use Fcntl;
|
Line 30 use Fcntl;
|
use Tie::RefHash; |
use Tie::RefHash; |
use Crypt::IDEA; |
use Crypt::IDEA; |
|
|
|
my $status=''; |
|
my $lastlog=''; |
|
|
# grabs exception and records it to log before exiting |
# grabs exception and records it to log before exiting |
sub catchexception { |
sub catchexception { |
my ($signal)=@_; |
my ($signal)=@_; |
Line 118 sub HUNTSMAN { # si
|
Line 121 sub HUNTSMAN { # si
|
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
map { |
map { |
$wasserver=$children{$_}; |
$wasserver=$children{$_}; |
|
&status("Closing $wasserver"); |
&logthis('Closing '.$wasserver.': '.&subreply('exit',$wasserver)); |
&logthis('Closing '.$wasserver.': '.&subreply('exit',$wasserver)); |
|
&status("Kill PID $_ for $wasserver"); |
kill ('INT',$_); |
kill ('INT',$_); |
} keys %children; |
} keys %children; |
my $execdir=$perlvar{'lonDaemons'}; |
my $execdir=$perlvar{'lonDaemons'}; |
Line 131 sub HUPSMAN { # sig
|
Line 136 sub HUPSMAN { # sig
|
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
map { |
map { |
$wasserver=$children{$_}; |
$wasserver=$children{$_}; |
|
&status("Closing $wasserver"); |
&logthis('Closing '.$wasserver.': '.&subreply('exit',$wasserver)); |
&logthis('Closing '.$wasserver.': '.&subreply('exit',$wasserver)); |
|
&status("Kill PID $_ for $wasserver"); |
kill ('INT',$_); |
kill ('INT',$_); |
} keys %children; |
} keys %children; |
&logthis("<font color=red>CRITICAL: Restarting</font>"); |
&logthis("<font color=red>CRITICAL: Restarting</font>"); |
Line 140 sub HUPSMAN { # sig
|
Line 147 sub HUPSMAN { # sig
|
exec("$execdir/lonc"); # here we go again |
exec("$execdir/lonc"); # here we go again |
} |
} |
|
|
|
sub checkchildren { |
|
&initnewstatus(); |
|
&logstatus(); |
|
&logthis('Going to check on the children'); |
|
map { |
|
sleep 1; |
|
unless (kill 'USR1' => $_) { |
|
&logthis ('Child '.$_.' is dead'); |
|
&logstatus($$.' is dead'); |
|
} |
|
} sort keys %children; |
|
} |
|
|
sub USRMAN { |
sub USRMAN { |
&logthis("USR1: Trying to establish connections again"); |
&logthis("USR1: Trying to establish connections again"); |
foreach $thisserver (keys %hostip) { |
foreach $thisserver (keys %hostip) { |
Line 149 sub USRMAN {
|
Line 169 sub USRMAN {
|
." >$answer<"); |
." >$answer<"); |
} |
} |
%childatt=(); |
%childatt=(); |
|
&checkchildren(); |
} |
} |
|
|
# -------------------------------------------------- Non-critical communication |
# -------------------------------------------------- Non-critical communication |
Line 161 sub subreply {
|
Line 182 sub subreply {
|
Type => SOCK_STREAM, |
Type => SOCK_STREAM, |
Timeout => 10) |
Timeout => 10) |
or return "con_lost"; |
or return "con_lost"; |
print $sclient "$cmd\n"; |
$SIG{ALRM}=sub { die "timeout" }; |
my $answer=<$sclient>; |
$SIG{__DIE__}='DEFAULT'; |
chomp($answer); |
eval { |
if (!$answer) { $answer="con_lost"; } |
alarm(10); |
|
print $sclient "$cmd\n"; |
|
my $answer=<$sclient>; |
|
chomp($answer); |
|
alarm(0); |
|
}; |
|
if ((!$answer) || ($@=~/timeout/)) { $answer="con_lost"; } |
|
$SIG{ALRM}='DEFAULT'; |
|
$SIG{__DIE__}=\&catchexception; |
} else { $answer='self_reply'; } |
} else { $answer='self_reply'; } |
return $answer; |
return $answer; |
} |
} |
Line 177 sub logthis {
|
Line 206 sub logthis {
|
my $fh=IO::File->new(">>$execdir/logs/lonc.log"); |
my $fh=IO::File->new(">>$execdir/logs/lonc.log"); |
my $now=time; |
my $now=time; |
my $local=localtime($now); |
my $local=localtime($now); |
|
$lastlog=$local.': '.$message; |
print $fh "$local ($$): $message\n"; |
print $fh "$local ($$): $message\n"; |
} |
} |
|
|
Line 189 sub logperm {
|
Line 219 sub logperm {
|
my $fh=IO::File->new(">>$execdir/logs/lonnet.perm.log"); |
my $fh=IO::File->new(">>$execdir/logs/lonnet.perm.log"); |
print $fh "$now:$message:$local\n"; |
print $fh "$now:$message:$local\n"; |
} |
} |
|
# ------------------------------------------------------------------ Log status |
|
|
|
sub logstatus { |
|
my $docdir=$perlvar{'lonDocRoot'}; |
|
my $fh=IO::File->new(">>$docdir/lon-status/loncstatus.txt"); |
|
print $fh $$."\t".$status."\t".$lastlog."\n"; |
|
} |
|
|
|
sub initnewstatus { |
|
my $docdir=$perlvar{'lonDocRoot'}; |
|
my $fh=IO::File->new(">$docdir/lon-status/loncstatus.txt"); |
|
my $now=time; |
|
my $local=localtime($now); |
|
print $fh "LONC status $local - parent $$\n\n"; |
|
} |
|
|
|
# -------------------------------------------------------------- Status setting |
|
|
|
sub status { |
|
my $what=shift; |
|
my $now=time; |
|
my $local=localtime($now); |
|
$status=$local.': '.$what; |
|
} |
|
|
|
|
# ---------------------------------------------------- Fork once and dissociate |
# ---------------------------------------------------- Fork once and dissociate |
|
|
Line 212 $SIG{HUP}=$SIG{USR1}='IGNORE';
|
Line 267 $SIG{HUP}=$SIG{USR1}='IGNORE';
|
|
|
# Fork off our children, one for every server |
# Fork off our children, one for every server |
|
|
|
&status("Forking ..."); |
|
|
foreach $thisserver (keys %hostip) { |
foreach $thisserver (keys %hostip) { |
make_new_child($thisserver); |
make_new_child($thisserver); |
} |
} |
Line 226 $SIG{USR1} = \&USRMAN;
|
Line 283 $SIG{USR1} = \&USRMAN;
|
|
|
# And maintain the population. |
# And maintain the population. |
while (1) { |
while (1) { |
|
&status("Sleeping"); |
sleep; # wait for a signal (i.e., child's death) |
sleep; # wait for a signal (i.e., child's death) |
# See who died and start new one |
# See who died and start new one |
|
&status("Woke up"); |
foreach $thisserver (keys %hostip) { |
foreach $thisserver (keys %hostip) { |
if (!$childpid{$thisserver}) { |
if (!$childpid{$thisserver}) { |
if ($childatt{$thisserver}<$childmaxattempts) { |
if ($childatt{$thisserver}<$childmaxattempts) { |
Line 265 sub make_new_child {
|
Line 324 sub make_new_child {
|
} else { |
} else { |
# Child can *not* return from this subroutine. |
# Child can *not* return from this subroutine. |
$SIG{INT} = 'DEFAULT'; # make SIGINT kill us as it did before |
$SIG{INT} = 'DEFAULT'; # make SIGINT kill us as it did before |
|
$SIG{USR1}= \&logstatus; |
|
|
# unblock signals |
# unblock signals |
sigprocmask(SIG_UNBLOCK, $sigset) |
sigprocmask(SIG_UNBLOCK, $sigset) |
or die "Can't unblock SIGINT for fork: $!\n"; |
or die "Can't unblock SIGINT for fork: $!\n"; |
Line 275 sub make_new_child {
|
Line 335 sub make_new_child {
|
$port = "$perlvar{'lonSockDir'}/$conserver"; |
$port = "$perlvar{'lonSockDir'}/$conserver"; |
|
|
unlink($port); |
unlink($port); |
|
|
# ---------------------------------------------------- Client to network server |
# ---------------------------------------------------- Client to network server |
|
|
|
&status("Opening TCP: $conserver"); |
|
|
unless ( |
unless ( |
$remotesock = IO::Socket::INET->new(PeerAddr => $hostip{$conserver}, |
$remotesock = IO::Socket::INET->new(PeerAddr => $hostip{$conserver}, |
PeerPort => $perlvar{'londPort'}, |
PeerPort => $perlvar{'londPort'}, |
Line 288 unless (
|
Line 352 unless (
|
sleep($st); |
sleep($st); |
exit; |
exit; |
}; |
}; |
# --------------------------------------- Send a ping to make other end do USR1 |
# ----------------------------------------------------------------- Init dialog |
|
|
|
&status("Init dialogue: $conserver"); |
|
|
|
$SIG{ALRM}=sub { die "timeout" }; |
|
$SIG{__DIE__}='DEFAULT'; |
|
eval { |
|
alarm(60); |
print $remotesock "init\n"; |
print $remotesock "init\n"; |
$answer=<$remotesock>; |
$answer=<$remotesock>; |
print $remotesock "$answer"; |
print $remotesock "$answer"; |
$answer=<$remotesock>; |
$answer=<$remotesock>; |
chomp($answer); |
chomp($answer); |
|
alarm(0); |
|
}; |
|
$SIG{ALRM}='DEFAULT'; |
|
$SIG{__DIE__}=\&catchexception; |
|
|
|
if ($@=~/timeout/) { |
|
&logthis("Timed out during init: $conserver"); |
|
exit; |
|
} |
|
|
|
|
&logthis("Init reply for $conserver: >$answer<"); |
&logthis("Init reply for $conserver: >$answer<"); |
if ($answer ne 'ok') { |
if ($answer ne 'ok') { |
my $st=120+int(rand(240)); |
my $st=120+int(rand(240)); |
Line 303 if ($answer ne 'ok') {
|
Line 385 if ($answer ne 'ok') {
|
exit; |
exit; |
} |
} |
sleep 5; |
sleep 5; |
|
&status("Ponging $conserver"); |
print $remotesock "pong\n"; |
print $remotesock "pong\n"; |
$answer=<$remotesock>; |
$answer=<$remotesock>; |
chomp($answer); |
chomp($answer); |
&logthis("Pong reply for $conserver: >$answer<"); |
&logthis("Pong reply for $conserver: >$answer<"); |
# ----------------------------------------------------------- Initialize cipher |
# ----------------------------------------------------------- Initialize cipher |
|
|
|
&status("Initialize cipher: $conserver"); |
print $remotesock "ekey\n"; |
print $remotesock "ekey\n"; |
my $buildkey=<$remotesock>; |
my $buildkey=<$remotesock>; |
my $key=$conserver.$perlvar{'lonHostID'}; |
my $key=$conserver.$perlvar{'lonHostID'}; |
Line 330 if ($cipher=new IDEA $cipherkey) {
|
Line 414 if ($cipher=new IDEA $cipherkey) {
|
} |
} |
|
|
# ----------------------------------------- We're online, send delayed messages |
# ----------------------------------------- We're online, send delayed messages |
|
&status("Checking for delayed messages"); |
my @allbuffered; |
my @allbuffered; |
my $path="$perlvar{'lonSockDir'}/delayed"; |
my $path="$perlvar{'lonSockDir'}/delayed"; |
opendir(DIRHANDLE,$path); |
opendir(DIRHANDLE,$path); |
Line 338 if ($cipher=new IDEA $cipherkey) {
|
Line 422 if ($cipher=new IDEA $cipherkey) {
|
closedir(DIRHANDLE); |
closedir(DIRHANDLE); |
my $dfname; |
my $dfname; |
map { |
map { |
|
&status("Sending delayed $conserver $_"); |
$dfname="$path/$_"; |
$dfname="$path/$_"; |
&logthis($dfname); |
&logthis($dfname); |
my $wcmd; |
my $wcmd; |
Line 360 if ($cipher=new IDEA $cipherkey) {
|
Line 445 if ($cipher=new IDEA $cipherkey) {
|
} |
} |
$cmd="enc:$cmdlength:$encrequest\n"; |
$cmd="enc:$cmdlength:$encrequest\n"; |
} |
} |
|
$SIG{ALRM}=sub { die "timeout" }; |
|
$SIG{__DIE__}='DEFAULT'; |
|
eval { |
|
alarm(60); |
print $remotesock "$cmd\n"; |
print $remotesock "$cmd\n"; |
$answer=<$remotesock>; |
$answer=<$remotesock>; |
chomp($answer); |
chomp($answer); |
if ($answer ne '') { |
alarm(0); |
|
}; |
|
$SIG{ALRM}='DEFAULT'; |
|
$SIG{__DIE__}=\&catchexception; |
|
|
|
if (($answer ne '') && ($@!~/timeout/)) { |
unlink("$dfname"); |
unlink("$dfname"); |
&logthis("Delayed $cmd to $conserver: >$answer<"); |
&logthis("Delayed $cmd to $conserver: >$answer<"); |
&logperm("S:$conserver:$bcmd"); |
&logperm("S:$conserver:$bcmd"); |
Line 372 if ($cipher=new IDEA $cipherkey) {
|
Line 465 if ($cipher=new IDEA $cipherkey) {
|
} @allbuffered; |
} @allbuffered; |
|
|
# ------------------------------------------------------- Listen to UNIX socket |
# ------------------------------------------------------- Listen to UNIX socket |
|
&status("Opening socket $conserver"); |
unless ( |
unless ( |
$server = IO::Socket::UNIX->new(Local => $port, |
$server = IO::Socket::UNIX->new(Local => $port, |
Type => SOCK_STREAM, |
Type => SOCK_STREAM, |
Line 413 while (1) {
|
Line 507 while (1) {
|
|
|
if ($client == $server) { |
if ($client == $server) { |
# accept a new connection |
# accept a new connection |
|
&status("Accept new connection: $conserver"); |
$client = $server->accept(); |
$client = $server->accept(); |
$select->add($client); |
$select->add($client); |
nonblock($client); |
nonblock($client); |
Line 428 while (1) {
|
Line 522 while (1) {
|
delete $outbuffer{$client}; |
delete $outbuffer{$client}; |
delete $ready{$client}; |
delete $ready{$client}; |
|
|
|
&status("Idle $conserver"); |
$select->remove($client); |
$select->remove($client); |
close $client; |
close $client; |
next; |
next; |
Line 512 sub handle {
|
Line 607 sub handle {
|
} |
} |
$request="enc:$cmdlength:$encrequest\n"; |
$request="enc:$cmdlength:$encrequest\n"; |
} |
} |
|
# --------------------------------------------------------------- Main exchange |
|
$SIG{ALRM}=sub { die "timeout" }; |
|
$SIG{__DIE__}='DEFAULT'; |
|
eval { |
|
alarm(300); |
|
&status("Sending $conserver: $request"); |
print $remotesock "$request"; |
print $remotesock "$request"; |
|
&status("Waiting for reply from $conserver: $request"); |
$answer=<$remotesock>; |
$answer=<$remotesock>; |
|
&status("Received reply: $request"); |
|
alarm(0); |
|
}; |
|
if ($@=~/timeout/) { |
|
$answer=''; |
|
&logthis( |
|
"<font color=red>CRITICAL: Timeout $conserver: $request</font>"); |
|
} |
|
$SIG{ALRM}='DEFAULT'; |
|
$SIG{__DIE__}=\&catchexception; |
|
|
|
|
if ($answer) { |
if ($answer) { |
if ($answer =~ /^enc/) { |
if ($answer =~ /^enc/) { |
my ($cmd,$cmdlength,$encinput)=split(/:/,$answer); |
my ($cmd,$cmdlength,$encinput)=split(/:/,$answer); |
Line 535 sub handle {
|
Line 649 sub handle {
|
# ===================================================== Done processing request |
# ===================================================== Done processing request |
} |
} |
delete $ready{$client}; |
delete $ready{$client}; |
|
&status("Completed $conserver: $request"); |
# -------------------------------------------------------------- End non-forker |
# -------------------------------------------------------------- End non-forker |
} |
} |
# ---------------------------------------------------------- End make_new_child |
# ---------------------------------------------------------- End make_new_child |