version 1.29, 2002/02/25 15:48:11
|
version 1.31, 2002/03/03 18:13:07
|
Line 60 use Crypt::IDEA;
|
Line 60 use Crypt::IDEA;
|
use Net::Ping; |
use Net::Ping; |
use LWP::UserAgent(); |
use LWP::UserAgent(); |
|
|
my $status=''; |
$status=''; |
my $lastlog=''; |
$lastlog=''; |
|
$conserver='SHELL'; |
# grabs exception and records it to log before exiting |
|
sub catchexception { |
|
my ($signal)=@_; |
|
$SIG{QUIT}='DEFAULT'; |
|
$SIG{__DIE__}='DEFAULT'; |
|
chomp($signal); |
|
&logthis("<font color=red>CRITICAL: " |
|
."ABNORMAL EXIT. Child $$ for server [$wasserver] died through " |
|
."\"$signal\" with parameter [$@]</font>"); |
|
die($@); |
|
} |
|
|
|
$childmaxattempts=5; |
|
|
|
# -------------------------------------- Routines to see if other box available |
|
|
|
sub online { |
|
my $host=shift; |
|
&status("Pinging ".$host); |
|
my $p=Net::Ping->new("tcp",20); |
|
my $online=$p->ping("$host"); |
|
$p->close(); |
|
undef ($p); |
|
return $online; |
|
} |
|
|
|
sub connected { |
|
my ($local,$remote)=@_; |
|
&status("Checking connection $local to $remote"); |
|
$local=~s/\W//g; |
|
$remote=~s/\W//g; |
|
|
|
unless ($hostname{$local}) { return 'local_unknown'; } |
|
unless ($hostname{$remote}) { return 'remote_unknown'; } |
|
|
|
unless (&online($hostname{$local})) { return 'local_offline'; } |
|
|
|
my $ua=new LWP::UserAgent; |
|
|
|
my $request=new HTTP::Request('GET', |
|
"http://".$hostname{$local}.'/cgi-bin/ping.pl?'.$remote); |
|
|
|
my $response=$ua->request($request); |
|
|
|
unless ($response->is_success) { return 'local_error'; } |
|
|
|
my $reply=$response->content; |
|
$reply=(split("\n",$reply))[0]; |
|
$reply=~s/\W//g; |
|
if ($reply ne $remote) { return $reply; } |
|
return 'ok'; |
|
} |
|
|
|
|
|
# -------------------------------- Set signal handlers to record abnormal exits |
# -------------------------------- Set signal handlers to record abnormal exits |
|
|
Line 182 close(CONFIG);
|
Line 129 close(CONFIG);
|
%childatt = (); # number of attempts to start server |
%childatt = (); # number of attempts to start server |
# for ID |
# for ID |
|
|
sub REAPER { # takes care of dead children |
$childmaxattempts=5; |
$SIG{CHLD} = \&REAPER; |
|
my $pid = wait; |
|
my $wasserver=$children{$pid}; |
|
&logthis("<font color=red>CRITICAL: " |
|
."Child $pid for server $wasserver died ($childatt{$wasserver})</font>"); |
|
delete $children{$pid}; |
|
delete $childpid{$wasserver}; |
|
my $port = "$perlvar{'lonSockDir'}/$wasserver"; |
|
unlink($port); |
|
} |
|
|
|
sub hangup { |
|
foreach (keys %children) { |
|
$wasserver=$children{$_}; |
|
&status("Closing $wasserver"); |
|
&logthis('Closing '.$wasserver.': '.&subreply('exit',$wasserver)); |
|
&status("Kill PID $_ for $wasserver"); |
|
kill ('INT',$_); |
|
} |
|
} |
|
|
|
sub HUNTSMAN { # signal handler for SIGINT |
|
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
|
&hangup(); |
|
my $execdir=$perlvar{'lonDaemons'}; |
|
unlink("$execdir/logs/lonc.pid"); |
|
&logthis("<font color=red>CRITICAL: Shutting down</font>"); |
|
exit; # clean up with dignity |
|
} |
|
|
|
sub HUPSMAN { # signal handler for SIGHUP |
|
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
|
&hangup(); |
|
&logthis("<font color=red>CRITICAL: Restarting</font>"); |
|
unlink("$execdir/logs/lonc.pid"); |
|
my $execdir=$perlvar{'lonDaemons'}; |
|
exec("$execdir/lonc"); # here we go again |
|
} |
|
|
|
sub checkchildren { |
|
&initnewstatus(); |
|
&logstatus(); |
|
&logthis('Going to check on the children'); |
|
foreach (sort keys %children) { |
|
sleep 1; |
|
unless (kill 'USR1' => $_) { |
|
&logthis ('<font color=red>CRITICAL: Child '.$_.' is dead</font>'); |
|
&logstatus($$.' is dead'); |
|
} |
|
} |
|
} |
|
|
|
sub USRMAN { |
|
&logthis("USR1: Trying to establish connections again"); |
|
%childatt=(); |
|
&checkchildren(); |
|
} |
|
|
|
# -------------------------------------------------- Non-critical communication |
|
sub subreply { |
|
my ($cmd,$server)=@_; |
|
my $answer=''; |
|
if ($server ne $perlvar{'lonHostID'}) { |
|
my $peerfile="$perlvar{'lonSockDir'}/$server"; |
|
my $sclient=IO::Socket::UNIX->new(Peer =>"$peerfile", |
|
Type => SOCK_STREAM, |
|
Timeout => 10) |
|
or return "con_lost"; |
|
|
|
|
|
$SIG{ALRM}=sub { die "timeout" }; |
|
$SIG{__DIE__}='DEFAULT'; |
|
eval { |
|
alarm(10); |
|
print $sclient "$cmd\n"; |
|
$answer=<$sclient>; |
|
chomp($answer); |
|
alarm(0); |
|
}; |
|
if ((!$answer) || ($@=~/timeout/)) { $answer="con_lost"; } |
|
$SIG{ALRM}='DEFAULT'; |
|
$SIG{__DIE__}=\&catchexception; |
|
} else { $answer='self_reply'; } |
|
return $answer; |
|
} |
|
|
|
# --------------------------------------------------------------------- Logging |
|
|
|
sub logthis { |
|
my $message=shift; |
|
my $execdir=$perlvar{'lonDaemons'}; |
|
my $fh=IO::File->new(">>$execdir/logs/lonc.log"); |
|
my $now=time; |
|
my $local=localtime($now); |
|
$lastlog=$local.': '.$message; |
|
print $fh "$local ($$) [$status]: $message\n"; |
|
} |
|
|
|
|
|
sub logperm { |
|
my $message=shift; |
|
my $execdir=$perlvar{'lonDaemons'}; |
|
my $now=time; |
|
my $local=localtime($now); |
|
my $fh=IO::File->new(">>$execdir/logs/lonnet.perm.log"); |
|
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 |
&status("Fork and dissociate"); |
&status("Fork and dissociate"); |
Line 324 die "Couldn't fork: $!" unless defined (
|
Line 139 die "Couldn't fork: $!" unless defined (
|
|
|
POSIX::setsid() or die "Can't start new session: $!"; |
POSIX::setsid() or die "Can't start new session: $!"; |
|
|
|
$conserver='PARENT'; |
|
|
# ------------------------------------------------------- Write our PID on disk |
# ------------------------------------------------------- Write our PID on disk |
&status("Write PID"); |
&status("Write PID"); |
$execdir=$perlvar{'lonDaemons'}; |
$execdir=$perlvar{'lonDaemons'}; |
Line 360 while (1) {
|
Line 177 while (1) {
|
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"); |
&status("Woke up"); |
|
my $skipping=''; |
foreach $thisserver (keys %hostip) { |
foreach $thisserver (keys %hostip) { |
if (!$childpid{$thisserver}) { |
if (!$childpid{$thisserver}) { |
if (($childatt{$thisserver}<$childmaxattempts) && |
if (($childatt{$thisserver}<$childmaxattempts) && |
Line 367 while (1) {
|
Line 185 while (1) {
|
$childatt{$thisserver}++; |
$childatt{$thisserver}++; |
&logthis( |
&logthis( |
"<font color=yellow>INFO: Trying to reconnect for $thisserver " |
"<font color=yellow>INFO: Trying to reconnect for $thisserver " |
."(".($childatt{$thisserver}?$childatt{$thisserver}:'none'). |
."($childatt{$thisserver} of $childmaxattempts attempts)</font>"); |
" of $childmaxattempts attempts)</font>"); |
|
make_new_child($thisserver); |
make_new_child($thisserver); |
} else { |
} else { |
&logthis( |
$skipping.=$thisserver.' '; |
"<font color=yellow>INFO: Skipping $thisserver " |
|
."($childatt{$thisserver} of $childmaxattempts attempts)</font>"); |
|
} |
} |
|
|
} |
} |
} |
} |
|
if ($skipping) { |
|
&logthis("<font color=blue>WARNING: Skipped $skipping</font>"); |
|
} |
} |
} |
|
|
|
|
sub make_new_child { |
sub make_new_child { |
|
|
my $conserver=shift; |
$newserver=shift; |
my $pid; |
my $pid; |
my $sigset; |
my $sigset; |
&logthis("Attempting to start child for server $conserver"); |
&logthis("Attempting to start child for server $newserver"); |
# block signal for fork |
# block signal for fork |
$sigset = POSIX::SigSet->new(SIGINT); |
$sigset = POSIX::SigSet->new(SIGINT); |
sigprocmask(SIG_BLOCK, $sigset) |
sigprocmask(SIG_BLOCK, $sigset) |
Line 398 sub make_new_child {
|
Line 216 sub make_new_child {
|
# Parent records the child's birth and returns. |
# Parent records the child's birth and returns. |
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"; |
$children{$pid} = $conserver; |
$children{$pid} = $newserver; |
$childpid{$conserver} = $pid; |
$childpid{$conserver} = $pid; |
return; |
return; |
} else { |
} else { |
|
$conserver=$newserver; |
# 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; |
$SIG{USR1}= \&logstatus; |
Line 429 unlink($port);
|
Line 248 unlink($port);
|
closedir(DIRHANDLE); |
closedir(DIRHANDLE); |
my $dfname; |
my $dfname; |
foreach (@allbuffered) { |
foreach (@allbuffered) { |
&status("Sending delayed $conserver $_"); |
&status("Sending delayed: $_"); |
$dfname="$path/$_"; |
$dfname="$path/$_"; |
&logthis('Sending '.$dfname); |
&logthis('Sending '.$dfname); |
my $wcmd; |
my $wcmd; |
Line 466 unlink($port);
|
Line 285 unlink($port);
|
|
|
if (($answer ne '') && ($@!~/timeout/)) { |
if (($answer ne '') && ($@!~/timeout/)) { |
unlink("$dfname"); |
unlink("$dfname"); |
&logthis("Delayed $cmd to $conserver: >$answer<"); |
&logthis("Delayed $cmd: >$answer<"); |
&logperm("S:$conserver:$bcmd"); |
&logperm("S:$conserver:$bcmd"); |
} |
} |
} |
} |
|
|
# ------------------------------------------------------- Listen to UNIX socket |
# ------------------------------------------------------- Listen to UNIX socket |
&status("Opening socket $conserver"); |
&status("Opening socket"); |
unless ( |
unless ( |
$server = IO::Socket::UNIX->new(Local => $port, |
$server = IO::Socket::UNIX->new(Local => $port, |
Type => SOCK_STREAM, |
Type => SOCK_STREAM, |
Line 481 unless (
|
Line 300 unless (
|
my $st=120+int(rand(240)); |
my $st=120+int(rand(240)); |
&logthis( |
&logthis( |
"<font color=blue>WARNING: ". |
"<font color=blue>WARNING: ". |
"Can't make server socket $conserver ($st secs): $@</font>"); |
"Can't make server socket ($st secs): $@</font>"); |
sleep($st); |
sleep($st); |
exit; |
exit; |
}; |
}; |
Line 529 while (1) {
|
Line 348 while (1) {
|
delete $outbuffer{$client}; |
delete $outbuffer{$client}; |
delete $ready{$client}; |
delete $ready{$client}; |
|
|
&status("Idle $conserver"); |
&status("Idle"); |
$select->remove($client); |
$select->remove($client); |
close $client; |
close $client; |
next; |
next; |
Line 559 while (1) {
|
Line 378 while (1) {
|
|
|
$rv = $client->send($outbuffer{$client}, 0); |
$rv = $client->send($outbuffer{$client}, 0); |
|
|
unless ($outbuffer{$client}=~/con_lost\n$/) { |
unless ($outbuffer{$client} eq "con_lost\n") { |
unless (defined $rv) { |
unless (defined $rv) { |
# Whine, but move on. |
# Whine, but move on. |
&logthis("I was told I could write, but I can't.\n"); |
&logthis("I was told I could write, but I can't.\n"); |
Line 588 while (1) {
|
Line 407 while (1) {
|
} else { |
} else { |
# -------------------------------------------------------- Wow, connection lost |
# -------------------------------------------------------- Wow, connection lost |
&logthis( |
&logthis( |
"<font color=red>CRITICAL: Closing connection $conserver</font>"); |
"<font color=red>CRITICAL: Closing connection</font>"); |
&status("Connection lost $conserver"); |
&status("Connection lost"); |
$remotesock->shutdown(2); |
$remotesock->shutdown(2); |
&logthis("Attempting to open new connection"); |
&logthis("Attempting to open new connection"); |
&openremote($conserver); |
&openremote($conserver); |
Line 614 sub handle {
|
Line 433 sub handle {
|
# put text of reply into $outbuffer{$client} |
# put text of reply into $outbuffer{$client} |
# ------------------------------------------------------------ Is this the end? |
# ------------------------------------------------------------ Is this the end? |
if ($request eq "close_connection_exit\n") { |
if ($request eq "close_connection_exit\n") { |
&status("Request close connection: $conserver"); |
&status("Request close connection"); |
&logthis( |
&logthis( |
"<font color=red>CRITICAL: Request Close Connection $conserver</font>"); |
"<font color=red>CRITICAL: Request Close Connection</font>"); |
$remotesock->shutdown(2); |
$remotesock->shutdown(2); |
$server->close(); |
$server->close(); |
exit; |
exit; |
Line 640 sub handle {
|
Line 459 sub handle {
|
$SIG{__DIE__}='DEFAULT'; |
$SIG{__DIE__}='DEFAULT'; |
eval { |
eval { |
alarm(300); |
alarm(300); |
&status("Sending $conserver: $request"); |
&status("Sending: $request"); |
print $remotesock "$request"; |
print $remotesock "$request"; |
&status("Waiting for reply from $conserver: $request"); |
&status("Waiting for reply from $conserver: $request"); |
$answer=<$remotesock>; |
$answer=<$remotesock>; |
Line 650 sub handle {
|
Line 469 sub handle {
|
if ($@=~/timeout/) { |
if ($@=~/timeout/) { |
$answer=''; |
$answer=''; |
&logthis( |
&logthis( |
"<font color=red>CRITICAL: Timeout $conserver: $request</font>"); |
"<font color=red>CRITICAL: Timeout: $request</font>"); |
} |
} |
$SIG{ALRM}='DEFAULT'; |
$SIG{ALRM}='DEFAULT'; |
$SIG{__DIE__}=\&catchexception; |
$SIG{__DIE__}=\&catchexception; |
Line 674 sub handle {
|
Line 493 sub handle {
|
$outbuffer{$client} .= "con_lost\n"; |
$outbuffer{$client} .= "con_lost\n"; |
} |
} |
|
|
|
&status("Completed: $request"); |
|
|
# ===================================================== 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 |
Line 701 sub openremote {
|
Line 521 sub openremote {
|
|
|
my $conserver=shift; |
my $conserver=shift; |
|
|
&status("Opening TCP: $conserver"); |
&status("Opening TCP"); |
|
|
unless ( |
unless ( |
$remotesock = IO::Socket::INET->new(PeerAddr => $hostip{$conserver}, |
$remotesock = IO::Socket::INET->new(PeerAddr => $hostip{$conserver}, |
Line 711 unless (
|
Line 531 unless (
|
) { |
) { |
my $st=120+int(rand(240)); |
my $st=120+int(rand(240)); |
&logthis( |
&logthis( |
"<font color=blue>WARNING: Couldn't connect $conserver ($st secs): $@</font>"); |
"<font color=blue>WARNING: Couldn't connect ($st secs): $@</font>"); |
sleep($st); |
sleep($st); |
exit; |
exit; |
}; |
}; |
Line 734 chomp($answer);
|
Line 554 chomp($answer);
|
$SIG{__DIE__}=\&catchexception; |
$SIG{__DIE__}=\&catchexception; |
|
|
if ($@=~/timeout/) { |
if ($@=~/timeout/) { |
&logthis("Timed out during init: $conserver"); |
&logthis("Timed out during init"); |
exit; |
exit; |
} |
} |
|
|
if ($answer ne 'ok') { |
if ($answer ne 'ok') { |
&logthis("Init reply for $conserver: >$answer<"); |
&logthis("Init reply: >$answer<"); |
my $st=120+int(rand(240)); |
my $st=120+int(rand(240)); |
&logthis( |
&logthis( |
"<font color=blue>WARNING: Init failed $conserver ($st secs)</font>"); |
"<font color=blue>WARNING: Init failed ($st secs)</font>"); |
sleep($st); |
sleep($st); |
exit; |
exit; |
} |
} |
|
|
sleep 5; |
sleep 5; |
&status("Ponging $conserver"); |
&status("Ponging"); |
print $remotesock "pong\n"; |
print $remotesock "pong\n"; |
$answer=<$remotesock>; |
$answer=<$remotesock>; |
chomp($answer); |
chomp($answer); |
if ($answer!~/^$converver/) { |
if ($answer!~/^$conserver/) { |
&logthis("Pong reply for $conserver: >$answer<"); |
&logthis("Pong reply: >$answer<"); |
} |
} |
# ----------------------------------------------------------- Initialize cipher |
# ----------------------------------------------------------- Initialize cipher |
|
|
&status("Initialize cipher: $conserver"); |
&status("Initialize cipher"); |
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 768 $key=$key.$buildkey.$key.$buildkey.$key.
|
Line 588 $key=$key.$buildkey.$key.$buildkey.$key.
|
$key=substr($key,0,32); |
$key=substr($key,0,32); |
my $cipherkey=pack("H32",$key); |
my $cipherkey=pack("H32",$key); |
if ($cipher=new IDEA $cipherkey) { |
if ($cipher=new IDEA $cipherkey) { |
&logthis("Secure connection initialized: $conserver"); |
&logthis("Secure connection initialized"); |
} else { |
} else { |
my $st=120+int(rand(240)); |
my $st=120+int(rand(240)); |
&logthis( |
&logthis( |
"<font color=blue>WARNING: ". |
"<font color=blue>WARNING: ". |
"Could not establish secure connection, $conserver ($st secs)!</font>"); |
"Could not establish secure connection ($st secs)!</font>"); |
sleep($st); |
sleep($st); |
exit; |
exit; |
} |
} |
|
|
} |
} |
|
|
|
|
|
|
|
# grabs exception and records it to log before exiting |
|
sub catchexception { |
|
my ($signal)=@_; |
|
$SIG{QUIT}='DEFAULT'; |
|
$SIG{__DIE__}='DEFAULT'; |
|
chomp($signal); |
|
&logthis("<font color=red>CRITICAL: " |
|
."ABNORMAL EXIT. Child $$ for server [$wasserver] died through " |
|
."\"$signal\" with parameter [$@]</font>"); |
|
die($@); |
|
} |
|
|
|
# -------------------------------------- Routines to see if other box available |
|
|
|
sub online { |
|
my $host=shift; |
|
&status("Pinging ".$host); |
|
my $p=Net::Ping->new("tcp",20); |
|
my $online=$p->ping("$host"); |
|
$p->close(); |
|
undef ($p); |
|
return $online; |
|
} |
|
|
|
sub connected { |
|
my ($local,$remote)=@_; |
|
&status("Checking connection $local to $remote"); |
|
$local=~s/\W//g; |
|
$remote=~s/\W//g; |
|
|
|
unless ($hostname{$local}) { return 'local_unknown'; } |
|
unless ($hostname{$remote}) { return 'remote_unknown'; } |
|
|
|
unless (&online($hostname{$local})) { return 'local_offline'; } |
|
|
|
my $ua=new LWP::UserAgent; |
|
|
|
my $request=new HTTP::Request('GET', |
|
"http://".$hostname{$local}.'/cgi-bin/ping.pl?'.$remote); |
|
|
|
my $response=$ua->request($request); |
|
|
|
unless ($response->is_success) { return 'local_error'; } |
|
|
|
my $reply=$response->content; |
|
$reply=(split("\n",$reply))[0]; |
|
$reply=~s/\W//g; |
|
if ($reply ne $remote) { return $reply; } |
|
return 'ok'; |
|
} |
|
|
|
|
|
sub REAPER { # takes care of dead children |
|
$SIG{CHLD} = \&REAPER; |
|
my $pid = wait; |
|
my $wasserver=$children{$pid}; |
|
&logthis("<font color=red>CRITICAL: " |
|
."Child $pid for server $wasserver died ($childatt{$wasserver})</font>"); |
|
delete $children{$pid}; |
|
delete $childpid{$wasserver}; |
|
my $port = "$perlvar{'lonSockDir'}/$wasserver"; |
|
unlink($port); |
|
} |
|
|
|
sub hangup { |
|
foreach (keys %children) { |
|
$wasserver=$children{$_}; |
|
&status("Closing $wasserver"); |
|
&logthis('Closing '.$wasserver.': '.&subreply('exit',$wasserver)); |
|
&status("Kill PID $_ for $wasserver"); |
|
kill ('INT',$_); |
|
} |
|
} |
|
|
|
sub HUNTSMAN { # signal handler for SIGINT |
|
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
|
&hangup(); |
|
my $execdir=$perlvar{'lonDaemons'}; |
|
unlink("$execdir/logs/lonc.pid"); |
|
&logthis("<font color=red>CRITICAL: Shutting down</font>"); |
|
exit; # clean up with dignity |
|
} |
|
|
|
sub HUPSMAN { # signal handler for SIGHUP |
|
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
|
&hangup(); |
|
&logthis("<font color=red>CRITICAL: Restarting</font>"); |
|
unlink("$execdir/logs/lonc.pid"); |
|
my $execdir=$perlvar{'lonDaemons'}; |
|
exec("$execdir/lonc"); # here we go again |
|
} |
|
|
|
sub checkchildren { |
|
&initnewstatus(); |
|
&logstatus(); |
|
&logthis('Going to check on the children'); |
|
foreach (sort keys %children) { |
|
sleep 1; |
|
unless (kill 'USR1' => $_) { |
|
&logthis ('<font color=red>CRITICAL: Child '.$_.' is dead</font>'); |
|
&logstatus($$.' is dead'); |
|
} |
|
} |
|
} |
|
|
|
sub USRMAN { |
|
&logthis("USR1: Trying to establish connections again"); |
|
%childatt=(); |
|
&checkchildren(); |
|
} |
|
|
|
# -------------------------------------------------- Non-critical communication |
|
sub subreply { |
|
my ($cmd,$server)=@_; |
|
my $answer=''; |
|
if ($server ne $perlvar{'lonHostID'}) { |
|
my $peerfile="$perlvar{'lonSockDir'}/$server"; |
|
my $sclient=IO::Socket::UNIX->new(Peer =>"$peerfile", |
|
Type => SOCK_STREAM, |
|
Timeout => 10) |
|
or return "con_lost"; |
|
|
|
|
|
$SIG{ALRM}=sub { die "timeout" }; |
|
$SIG{__DIE__}='DEFAULT'; |
|
eval { |
|
alarm(10); |
|
print $sclient "$cmd\n"; |
|
$answer=<$sclient>; |
|
chomp($answer); |
|
alarm(0); |
|
}; |
|
if ((!$answer) || ($@=~/timeout/)) { $answer="con_lost"; } |
|
$SIG{ALRM}='DEFAULT'; |
|
$SIG{__DIE__}=\&catchexception; |
|
} else { $answer='self_reply'; } |
|
return $answer; |
|
} |
|
|
|
# --------------------------------------------------------------------- Logging |
|
|
|
sub logthis { |
|
my $message=shift; |
|
my $execdir=$perlvar{'lonDaemons'}; |
|
my $fh=IO::File->new(">>$execdir/logs/lonc.log"); |
|
my $now=time; |
|
my $local=localtime($now); |
|
$lastlog=$local.': '.$message; |
|
print $fh "$local ($$) [$conserver] [$status]: $message\n"; |
|
} |
|
|
|
|
|
sub logperm { |
|
my $message=shift; |
|
my $execdir=$perlvar{'lonDaemons'}; |
|
my $now=time; |
|
my $local=localtime($now); |
|
my $fh=IO::File->new(">>$execdir/logs/lonnet.perm.log"); |
|
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".$conserver."\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; |
|
} |
|
|
|
|
|
|
# ----------------------------------- POD (plain old documentation, CPAN style) |
# ----------------------------------- POD (plain old documentation, CPAN style) |
|
|
=head1 NAME |
=head1 NAME |
Line 788 lonc - LON TCP-MySQL-Server Daemon for h
|
Line 797 lonc - LON TCP-MySQL-Server Daemon for h
|
|
|
=head1 SYNOPSIS |
=head1 SYNOPSIS |
|
|
|
Usage: B<lonc> |
|
|
Should only be run as user=www. This is a command-line script which |
Should only be run as user=www. This is a command-line script which |
is invoked by loncron. |
is invoked by B<loncron>. There is no expectation that a typical user |
|
will manually start B<lonc> from the command-line. (In other words, |
|
DO NOT START B<lonc> YOURSELF.) |
|
|
=head1 DESCRIPTION |
=head1 DESCRIPTION |
|
|
Provides persistent TCP connections to the other servers in the network |
Provides persistent TCP connections to the other servers in the network |
through multiplexed domain sockets |
through multiplexed domain sockets |
|
|
PID in subdir logs/lonc.pid |
B<lonc> forks off children processes that correspond to the other servers |
kill kills |
in the network. Management of these processes can be done at the |
HUP restarts |
parent process level or the child process level. |
USR1 tries to open connections again |
|
|
B<logs/lonc.log> is the location of log messages. |
|
|
|
The process management is now explained in terms of linux shell commands, |
|
subroutines internal to this code, and signal assignments: |
|
|
|
=over 4 |
|
|
|
=item * |
|
|
|
PID is stored in B<logs/lonc.pid> |
|
|
|
This is the process id number of the parent B<lonc> process. |
|
|
|
=item * |
|
|
|
SIGTERM and SIGINT |
|
|
|
Parent signal assignment: |
|
$SIG{INT} = $SIG{TERM} = \&HUNTSMAN; |
|
|
|
Child signal assignment: |
|
$SIG{INT} = 'DEFAULT'; (and SIGTERM is DEFAULT also) |
|
(The child dies and a SIGALRM is sent to parent, awaking parent from slumber |
|
to restart a new child.) |
|
|
|
Command-line invocations: |
|
B<kill> B<-s> SIGTERM I<PID> |
|
B<kill> B<-s> SIGINT I<PID> |
|
|
|
Subroutine B<HUNTSMAN>: |
|
This is only invoked for the B<lonc> parent I<PID>. |
|
This kills all the children, and then the parent. |
|
The B<lonc.pid> file is cleared. |
|
|
|
=item * |
|
|
|
SIGHUP |
|
|
|
Current bug: |
|
This signal can only be processed the first time |
|
on the parent process. Subsequent SIGHUP signals |
|
have no effect. |
|
|
|
Parent signal assignment: |
|
$SIG{HUP} = \&HUPSMAN; |
|
|
|
Child signal assignment: |
|
none (nothing happens) |
|
|
|
Command-line invocations: |
|
B<kill> B<-s> SIGHUP I<PID> |
|
|
|
Subroutine B<HUPSMAN>: |
|
This is only invoked for the B<lonc> parent I<PID>, |
|
This kills all the children, and then the parent. |
|
The B<lonc.pid> file is cleared. |
|
|
|
=item * |
|
|
|
SIGUSR1 |
|
|
|
Parent signal assignment: |
|
$SIG{USR1} = \&USRMAN; |
|
|
|
Child signal assignment: |
|
$SIG{USR1}= \&logstatus; |
|
|
|
Command-line invocations: |
|
B<kill> B<-s> SIGUSR1 I<PID> |
|
|
|
Subroutine B<USRMAN>: |
|
When invoked for the B<lonc> parent I<PID>, |
|
SIGUSR1 is sent to all the children, and the status of |
|
each connection is logged. |
|
|
|
=item * |
|
|
|
SIGCHLD |
|
|
|
Parent signal assignment: |
|
$SIG{CHLD} = \&REAPER; |
|
|
|
Child signal assignment: |
|
none |
|
|
|
Command-line invocations: |
|
B<kill> B<-s> SIGCHLD I<PID> |
|
|
=head1 README |
Subroutine B<REAPER>: |
|
This is only invoked for the B<lonc> parent I<PID>. |
|
Information pertaining to the child is removed. |
|
The socket port is cleaned up. |
|
|
Not yet written. |
=back |
|
|
=head1 PREREQUISITES |
=head1 PREREQUISITES |
|
|