version 1.1.1.1, 1999/10/13 17:48:51
|
version 1.10, 2000/12/05 19:03:55
|
Line 10
|
Line 10
|
# HUP restarts |
# HUP restarts |
# USR1 tries to open connections again |
# USR1 tries to open connections again |
|
|
# 6/4/99,6/5,6/7,6/8,6/9,6/10,6/11,6/12,7/14,7/19,10/8,10/9 Gerd Kortemeyer |
# 6/4/99,6/5,6/7,6/8,6/9,6/10,6/11,6/12,7/14,7/19, |
|
# 10/8,10/9,10/15,11/18,12/22, |
|
# 2/8,7/25 Gerd Kortemeyer |
|
# 12/05 Scott Harrison |
|
# 12/05 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 23 use Fcntl;
|
Line 28 use Fcntl;
|
use Tie::RefHash; |
use Tie::RefHash; |
use Crypt::IDEA; |
use Crypt::IDEA; |
|
|
|
# grabs exception and records it to log before exiting |
|
sub catchexception { |
|
my ($signal)=@_; |
|
$SIG{'QUIT'}='DEFAULT'; |
|
$SIG{__DIE__}='DEFAULT'; |
|
&logthis("<font color=red>CRITICAL: " |
|
."ABNORMAL EXIT. Child $$ for server $wasserver died through " |
|
."$signal with this parameter->[$@]</font>"); |
|
die($@); |
|
} |
|
|
|
# grabs exception and records it to log before exiting |
|
# NOTE: we must NOT use the regular (non-overrided) die function in |
|
# the code because a handler CANNOT be attached to it |
|
# (despite what some of the documentation says about SIG{__DIE__}. |
|
sub catchdie { |
|
my ($message)=@_; |
|
$SIG{'QUIT'}='DEFAULT'; |
|
$SIG{__DIE__}='DEFAULT'; |
|
&logthis("<font color=red>CRITICAL: " |
|
."ABNORMAL EXIT. Child $$ for server $wasserver died through " |
|
."\_\_DIE\_\_ with this parameter->[$message]</font>"); |
|
die($message); |
|
} |
|
|
|
$childmaxattempts=10; |
|
|
|
# -------------------------------- Set signal handlers to record abnormal exits |
|
|
|
$SIG{'QUIT'}=\&catchexception; |
|
$SIG{__DIE__}=\&catchexception; |
|
|
# ------------------------------------ Read httpd access.conf and get variables |
# ------------------------------------ Read httpd access.conf and get variables |
|
|
open (CONFIG,"/etc/httpd/conf/access.conf") || die "Can't read access.conf"; |
open (CONFIG,"/etc/httpd/conf/access.conf") |
|
|| catchdie "Can't read access.conf"; |
|
|
while ($configline=<CONFIG>) { |
while ($configline=<CONFIG>) { |
if ($configline =~ /PerlSetVar/) { |
if ($configline =~ /PerlSetVar/) { |
my ($dummy,$varname,$varvalue)=split(/\s+/,$configline); |
my ($dummy,$varname,$varvalue)=split(/\s+/,$configline); |
|
chomp($varvalue); |
$perlvar{$varname}=$varvalue; |
$perlvar{$varname}=$varvalue; |
} |
} |
} |
} |
close(CONFIG); |
close(CONFIG); |
|
|
|
# --------------------------------------------- Check if other instance running |
|
|
|
my $pidfile="$perlvar{'lonDaemons'}/logs/lonc.pid"; |
|
|
|
if (-e $pidfile) { |
|
my $lfh=IO::File->new("$pidfile"); |
|
my $pide=<$lfh>; |
|
chomp($pide); |
|
if (kill 0 => $pide) { catchdie "already running"; } |
|
} |
|
|
# ------------------------------------------------------------- Read hosts file |
# ------------------------------------------------------------- Read hosts file |
|
|
open (CONFIG,"$perlvar{'lonTabDir'}/hosts.tab") || die "Can't read host file"; |
open (CONFIG,"$perlvar{'lonTabDir'}/hosts.tab") |
|
|| catchdie "Can't read host file"; |
|
|
while ($configline=<CONFIG>) { |
while ($configline=<CONFIG>) { |
my ($id,$domain,$role,$name,$ip)=split(/:/,$configline); |
my ($id,$domain,$role,$name,$ip)=split(/:/,$configline); |
Line 59 sub REAPER { # ta
|
Line 110 sub REAPER { # ta
|
$SIG{CHLD} = \&REAPER; |
$SIG{CHLD} = \&REAPER; |
my $pid = wait; |
my $pid = wait; |
my $wasserver=$children{$pid}; |
my $wasserver=$children{$pid}; |
&logthis("Child $pid for server $wasserver died"); |
&logthis("<font color=red>CRITICAL: " |
|
."Child $pid for server $wasserver died ($childatt{$wasserver})</font>"); |
delete $children{$pid}; |
delete $children{$pid}; |
delete $childpid{$wasserver}; |
delete $childpid{$wasserver}; |
my $port = "$perlvar{'lonSockDir'}/$wasserver"; |
my $port = "$perlvar{'lonSockDir'}/$wasserver"; |
Line 71 sub HUNTSMAN { # si
|
Line 123 sub HUNTSMAN { # si
|
kill 'INT' => keys %children; |
kill 'INT' => keys %children; |
my $execdir=$perlvar{'lonDaemons'}; |
my $execdir=$perlvar{'lonDaemons'}; |
unlink("$execdir/logs/lonc.pid"); |
unlink("$execdir/logs/lonc.pid"); |
&logthis("Shutting down"); |
&logthis("<font color=red>CRITICAL: Shutting down</font>"); |
exit; # clean up with dignity |
exit; # clean up with dignity |
} |
} |
|
|
sub HUPSMAN { # signal handler for SIGHUP |
sub HUPSMAN { # signal handler for SIGHUP |
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
local($SIG{CHLD}) = 'IGNORE'; # we're going to kill our children |
kill 'INT' => keys %children; |
kill 'INT' => keys %children; |
&logthis("Restarting"); |
&logthis("<font color=red>CRITICAL: Restarting</font>"); |
my $execdir=$perlvar{'lonDaemons'}; |
my $execdir=$perlvar{'lonDaemons'}; |
exec("$execdir/lonc"); # here we go again |
exec("$execdir/lonc"); # here we go again |
} |
} |
|
|
sub USRMAN { |
sub USRMAN { |
%childatt=(); |
|
&logthis("USR1: Trying to establish connections again"); |
&logthis("USR1: Trying to establish connections again"); |
foreach $thisserver (keys %hostip) { |
foreach $thisserver (keys %hostip) { |
$answer=subreply("ping",$thisserver); |
$answer=subreply("ping",$thisserver); |
&logthis( |
&logthis("USR1: Ping $thisserver " |
"USR1: Ping $thisserver (pid >$childpid{$thisserver}<): >$answer<"); |
."(pid >$childpid{$thisserver}<, $childatt{thisserver} attempts): " |
|
." >$answer<"); |
} |
} |
|
%childatt=(); |
} |
} |
|
|
# -------------------------------------------------- Non-critical communication |
# -------------------------------------------------- Non-critical communication |
sub subreply { |
sub subreply { |
my ($cmd,$server)=@_; |
my ($cmd,$server)=@_; |
|
my $answer=''; |
if ($server ne $perlvar{'lonHostID'}) { |
if ($server ne $perlvar{'lonHostID'}) { |
my $peerfile="$perlvar{'lonSockDir'}/$server"; |
my $peerfile="$perlvar{'lonSockDir'}/$server"; |
my $sclient=IO::Socket::UNIX->new(Peer =>"$peerfile", |
my $sclient=IO::Socket::UNIX->new(Peer =>"$peerfile", |
Line 121 sub logthis {
|
Line 175 sub logthis {
|
print $fh "$local ($$): $message\n"; |
print $fh "$local ($$): $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"; |
|
} |
|
|
# ---------------------------------------------------- Fork once and dissociate |
# ---------------------------------------------------- Fork once and dissociate |
|
|
$fpid=fork; |
$fpid=fork; |
exit if $fpid; |
exit if $fpid; |
die "Couldn't fork: $!" unless defined ($fpid); |
catchdie "Couldn't fork: $!" unless defined ($fpid); |
|
|
POSIX::setsid() or die "Can't start new session: $!"; |
POSIX::setsid() or catchdie "Can't start new session: $!"; |
|
|
# ------------------------------------------------------- Write our PID on disk |
# ------------------------------------------------------- Write our PID on disk |
|
|
Line 135 $execdir=$perlvar{'lonDaemons'};
|
Line 199 $execdir=$perlvar{'lonDaemons'};
|
open (PIDSAVE,">$execdir/logs/lonc.pid"); |
open (PIDSAVE,">$execdir/logs/lonc.pid"); |
print PIDSAVE "$$\n"; |
print PIDSAVE "$$\n"; |
close(PIDSAVE); |
close(PIDSAVE); |
&logthis("---------- Starting ----------"); |
&logthis("<font color=red>CRITICAL: ---------- Starting ----------</font>"); |
|
|
# ----------------------------- Ignore signals generated during initial startup |
# ----------------------------- Ignore signals generated during initial startup |
$SIG{HUP}=$SIG{USR1}='IGNORE'; |
$SIG{HUP}=$SIG{USR1}='IGNORE'; |
Line 161 while (1) {
|
Line 225 while (1) {
|
# See who died and start new one |
# See who died and start new one |
foreach $thisserver (keys %hostip) { |
foreach $thisserver (keys %hostip) { |
if (!$childpid{$thisserver}) { |
if (!$childpid{$thisserver}) { |
if ($childatt{$thisserver}<5) { |
if ($childatt{$thisserver}<=$childmaxattempts) { |
|
$childatt{$thisserver}++; |
|
&logthis( |
|
"<font color=yellow>INFO: Trying to reconnect for $thisserver " |
|
."($childatt{$thisserver} of $childmaxattempts attempts)</font>"); |
make_new_child($thisserver); |
make_new_child($thisserver); |
$childatt{$thisserver}++; |
|
} |
} |
} |
} |
} |
} |
Line 179 sub make_new_child {
|
Line 246 sub make_new_child {
|
# 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) |
or die "Can't block SIGINT for fork: $!\n"; |
or catchdie "Can't block SIGINT for fork: $!\n"; |
|
|
die "fork: $!" unless defined ($pid = fork); |
catchdie "fork: $!" unless defined ($pid = fork); |
|
|
if ($pid) { |
if ($pid) { |
# 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 catchdie "Can't unblock SIGINT for fork: $!\n"; |
$children{$pid} = $conserver; |
$children{$pid} = $conserver; |
$childpid{$conserver} = $pid; |
$childpid{$conserver} = $pid; |
return; |
return; |
Line 196 sub make_new_child {
|
Line 263 sub make_new_child {
|
|
|
# unblock signals |
# unblock signals |
sigprocmask(SIG_UNBLOCK, $sigset) |
sigprocmask(SIG_UNBLOCK, $sigset) |
or die "Can't unblock SIGINT for fork: $!\n"; |
or catchdie "Can't unblock SIGINT for fork: $!\n"; |
|
|
# ----------------------------- This is the modified main program of non-forker |
# ----------------------------- This is the modified main program of non-forker |
|
|
Line 209 unless (
|
Line 276 unless (
|
PeerPort => $perlvar{'londPort'}, |
PeerPort => $perlvar{'londPort'}, |
Proto => "tcp", |
Proto => "tcp", |
Type => SOCK_STREAM) |
Type => SOCK_STREAM) |
) { &logthis("Couldn't connect $conserver: $@"); |
) { |
sleep(5); |
my $st=120+int(rand(240)); |
|
&logthis( |
|
"<font color=blue>WARNING: Couldn't connect $conserver ($st secs): $@</font>"); |
|
sleep($st); |
exit; |
exit; |
}; |
}; |
# --------------------------------------- Send a ping to make other end do USR1 |
# --------------------------------------- Send a ping to make other end do USR1 |
print $remotesock "ping\n"; |
print $remotesock "init\n"; |
|
$answer=<$remotesock>; |
|
print $remotesock "$answer"; |
$answer=<$remotesock>; |
$answer=<$remotesock>; |
chomp($answer); |
chomp($answer); |
&logthis("Ping reply for $conserver: >$answer<"); |
&logthis("Init reply for $conserver: >$answer<"); |
sleep 5; |
sleep 5; |
print $remotesock "pong\n"; |
print $remotesock "pong\n"; |
$answer=<$remotesock>; |
$answer=<$remotesock>; |
Line 237 my $cipherkey=pack("H32",$key);
|
Line 309 my $cipherkey=pack("H32",$key);
|
if ($cipher=new IDEA $cipherkey) { |
if ($cipher=new IDEA $cipherkey) { |
&logthis("Secure connection inititalized: $conserver"); |
&logthis("Secure connection inititalized: $conserver"); |
} else { |
} else { |
&logthis("Error: Could not establish secure connection, $conserver!"); |
my $st=120+int(rand(240)); |
} |
&logthis( |
|
"<font color=blue>WARNING: ". |
|
"Could not establish secure connection, $conserver ($st secs)!</font>"); |
|
sleep($st); |
|
exit; |
|
} |
|
|
|
# ----------------------------------------- We're online, send delayed messages |
|
|
|
my @allbuffered; |
|
my $path="$perlvar{'lonSockDir'}/delayed"; |
|
opendir(DIRHANDLE,$path); |
|
@allbuffered=grep /\.$conserver$/, readdir DIRHANDLE; |
|
closedir(DIRHANDLE); |
|
my $dfname; |
|
map { |
|
$dfname="$path/$_"; |
|
&logthis($dfname); |
|
my $wcmd; |
|
{ |
|
my $dfh=IO::File->new($dfname); |
|
$cmd=<$dfh>; |
|
} |
|
chomp($cmd); |
|
my $bcmd=$cmd; |
|
if ($cmd =~ /^encrypt\:/) { |
|
my $rcmd=$cmd; |
|
$rcmd =~ s/^encrypt\://; |
|
chomp($rcmd); |
|
my $cmdlength=length($rcmd); |
|
$rcmd.=" "; |
|
my $encrequest=''; |
|
for (my $encidx=0;$encidx<=$cmdlength;$encidx+=8) { |
|
$encrequest.= |
|
unpack("H16",$cipher->encrypt(substr($rcmd,$encidx,8))); |
|
} |
|
$cmd="enc:$cmdlength:$encrequest\n"; |
|
} |
|
|
|
print $remotesock "$cmd\n"; |
|
$answer=<$remotesock>; |
|
chomp($answer); |
|
if ($answer ne '') { |
|
unlink("$dfname"); |
|
&logthis("Delayed $cmd to $conserver: >$answer<"); |
|
&logperm("S:$conserver:$bcmd"); |
|
} |
|
} @allbuffered; |
|
|
# ------------------------------------------------------- Listen to UNIX socket |
# ------------------------------------------------------- Listen to UNIX socket |
unless ( |
unless ( |
$server = IO::Socket::UNIX->new(Local => $port, |
$server = IO::Socket::UNIX->new(Local => $port, |
Type => SOCK_STREAM, |
Type => SOCK_STREAM, |
Listen => 10 ) |
Listen => 10 ) |
) { &logthis("Can't make server socket $conserver: $@"); |
) { |
sleep(5); |
my $st=120+int(rand(240)); |
|
&logthis( |
|
"<font color=blue>WARNING: ". |
|
"Can't make server socket $conserver ($st secs): $@</font>"); |
|
sleep($st); |
exit; |
exit; |
}; |
}; |
|
|
# ----------------------------------------------------------------------------- |
# ----------------------------------------------------------------------------- |
|
|
|
&logthis("<font color=green>$conserver online</font>"); |
|
|
|
# ----------------------------------------------------------------------------- |
# begin with empty buffers |
# begin with empty buffers |
%inbuffer = (); |
%inbuffer = (); |
%outbuffer = (); |
%outbuffer = (); |
Line 405 sub nonblock {
|
Line 530 sub nonblock {
|
|
|
|
|
$flags = fcntl($socket, F_GETFL, 0) |
$flags = fcntl($socket, F_GETFL, 0) |
or die "Can't get flags for socket: $!\n"; |
or catchdie "Can't get flags for socket: $!\n"; |
fcntl($socket, F_SETFL, $flags | O_NONBLOCK) |
fcntl($socket, F_SETFL, $flags | O_NONBLOCK) |
or die "Can't make socket nonblocking: $!\n"; |
or catchdie "Can't make socket nonblocking: $!\n"; |
} |
} |
|
|
|
|
|
|
|
|
|
|