version 1.81, 2007/03/28 20:28:29
|
version 1.102, 2017/10/20 20:20:20
|
Line 26
|
Line 26
|
# http://www.lon-capa.org/ |
# http://www.lon-capa.org/ |
# |
# |
# |
# |
# new lonc handles n request out bver m connections to londs. |
# new lonc handles n request out over m connections to londs. |
# This module is based on the Event class. |
# This module is based on the Event class. |
# Development iterations: |
# Development iterations: |
# - Setup basic event loop. (done) |
# - Setup basic event loop. (done) |
Line 72 my %perlvar = %{$perlvarref};
|
Line 72 my %perlvar = %{$perlvarref};
|
# |
# |
# parent and shared variables. |
# parent and shared variables. |
|
|
my %ChildHash; # by pid -> host. |
my %ChildPid; # by pid -> host. |
|
my %ChildHost; # by host. |
my %listening_to; # Socket->host table for who the parent |
my %listening_to; # Socket->host table for who the parent |
# is listening to. |
# is listening to. |
my %parent_dispatchers; # host-> listener watcher events. |
my %parent_dispatchers; # host-> listener watcher events. |
Line 84 my $ClientConnection = 0; # Uniquifier f
|
Line 85 my $ClientConnection = 0; # Uniquifier f
|
|
|
my $DebugLevel = 0; |
my $DebugLevel = 0; |
my $NextDebugLevel= 2; # So Sigint can toggle this. |
my $NextDebugLevel= 2; # So Sigint can toggle this. |
my $IdleTimeout= 600; # Wait 10 minutes before pruning connections. |
my $IdleTimeout= 5*60; # Seconds to wait prior to pruning connections. |
|
|
my $LogTransactions = 0; # When True, all transactions/replies get logged. |
my $LogTransactions = 0; # When True, all transactions/replies get logged. |
my $executable = $0; # Get the full path to me. |
my $executable = $0; # Get the full path to me. |
Line 94 my $executable = $0; # Get the full
|
Line 95 my $executable = $0; # Get the full
|
# |
# |
my $RemoteHost; # Name of host child is talking to. |
my $RemoteHost; # Name of host child is talking to. |
my $RemoteHostId; # default lonid of host child is talking to. |
my $RemoteHostId; # default lonid of host child is talking to. |
|
my @all_host_ids; |
my $UnixSocketDir= $perlvar{'lonSockDir'}; |
my $UnixSocketDir= $perlvar{'lonSockDir'}; |
my $IdleConnections = Stack->new(); # Set of idle connections |
my $IdleConnections = Stack->new(); # Set of idle connections |
my %ActiveConnections; # Connections to the remote lond. |
my %ActiveConnections; # Connections to the remote lond. |
Line 156 sub LogPerm {
|
Line 158 sub LogPerm {
|
my $now=time; |
my $now=time; |
my $local=localtime($now); |
my $local=localtime($now); |
my $fh=IO::File->new(">>$execdir/logs/lonnet.perm.log"); |
my $fh=IO::File->new(">>$execdir/logs/lonnet.perm.log"); |
|
chomp($message); |
print $fh "$now:$message:$local\n"; |
print $fh "$now:$message:$local\n"; |
} |
} |
|
|
Line 346 sub child_exit {
|
Line 349 sub child_exit {
|
|
|
=head2 Tick |
=head2 Tick |
|
|
Invoked each timer tick. |
Invoked each timer tick. |
|
|
=cut |
=cut |
|
|
Line 438 Trigger disconnections of idle sockets.
|
Line 441 Trigger disconnections of idle sockets.
|
|
|
sub SetupTimer { |
sub SetupTimer { |
Debug(6, "SetupTimer"); |
Debug(6, "SetupTimer"); |
Event->timer(interval => 1, cb => \&Tick ); |
Event->timer(interval => 1, cb => \&Tick, |
|
hard => 1); |
} |
} |
|
|
=pod |
=pod |
Line 484 sub ServerToIdle {
|
Line 488 sub ServerToIdle {
|
|
|
Event callback for when a client socket is writable. |
Event callback for when a client socket is writable. |
|
|
This callback is established when a transaction reponse is |
This callback is established when a transaction response is |
avaiable from lond. The response is forwarded to the unix socket |
available from lond. The response is forwarded to the unix socket |
as it becomes writable in this sub. |
as it becomes writable in this sub. |
|
|
Parameters: |
Parameters: |
Line 500 the data and Event->w->fd is the socket
|
Line 504 the data and Event->w->fd is the socket
|
sub ClientWritable { |
sub ClientWritable { |
my $Event = shift; |
my $Event = shift; |
my $Watcher = $Event->w; |
my $Watcher = $Event->w; |
|
if (!defined($Watcher)) { |
|
&child_exit(-1,'No watcher for event in ClientWritable'); |
|
} |
my $Data = $Watcher->data; |
my $Data = $Watcher->data; |
my $Socket = $Watcher->fd; |
my $Socket = $Watcher->fd; |
|
|
Line 552 sub ClientWritable {
|
Line 559 sub ClientWritable {
|
if($errno == POSIX::EWOULDBLOCK || |
if($errno == POSIX::EWOULDBLOCK || |
$errno == POSIX::EAGAIN || |
$errno == POSIX::EAGAIN || |
$errno == POSIX::EINTR) { |
$errno == POSIX::EINTR) { |
# No action taken? |
# No action taken...the socket will be writable firing the event again |
|
# which will result in a retry of the write. |
} else { # Unanticipated errno. |
} else { # Unanticipated errno. |
&Debug(5,"ClientWritable error or peer shutdown".$RemoteHost); |
&Debug(5,"ClientWritable error or peer shutdown".$RemoteHost); |
$Watcher->cancel; # Stop the watcher. |
$Watcher->cancel; # Stop the watcher. |
Line 563 sub ClientWritable {
|
Line 571 sub ClientWritable {
|
} |
} |
} else { |
} else { |
$Watcher->cancel(); # A delayed request...just cancel. |
$Watcher->cancel(); # A delayed request...just cancel. |
|
return; |
} |
} |
} |
} |
|
|
Line 580 Parameters:
|
Line 589 Parameters:
|
|
|
=item Socket |
=item Socket |
|
|
Socket on which the lond transaction occured. This is a |
Socket on which the lond transaction occurred. This is a |
LondConnection. The data received is in the TransactionReply member. |
LondConnection. The data received are in the TransactionReply member. |
|
|
=item Transaction |
=item Transaction |
|
|
Line 602 sub CompleteTransaction {
|
Line 611 sub CompleteTransaction {
|
StartClientReply($Transaction, $data); |
StartClientReply($Transaction, $data); |
} else { # Delete deferred transaction file. |
} else { # Delete deferred transaction file. |
Log("SUCCESS", "A delayed transaction was completed"); |
Log("SUCCESS", "A delayed transaction was completed"); |
LogPerm("S:$Transaction->getClient() :".$Transaction->getRequest()); |
LogPerm("S:".$Socket->PeerLoncapaHim().":".$Transaction->getRequest()); |
unlink $Transaction->getFile(); |
unlink($Transaction->getFile()); |
} |
} |
} |
} |
|
|
Line 621 sub CompleteTransaction {
|
Line 630 sub CompleteTransaction {
|
|
|
=item data |
=item data |
|
|
The data to send to apached client. |
The data to send to apache client. |
|
|
=cut |
=cut |
|
|
Line 734 Parameters:
|
Line 743 Parameters:
|
|
|
=item Restart |
=item Restart |
|
|
nonzero if we are allowed to create a new connection. |
non-zero if we are allowed to create a new connection. |
|
|
=cut |
=cut |
|
|
Line 754 sub KillSocket {
|
Line 763 sub KillSocket {
|
delete ($ActiveTransactions{$Socket}); |
delete ($ActiveTransactions{$Socket}); |
} |
} |
if(exists($ActiveConnections{$Socket})) { |
if(exists($ActiveConnections{$Socket})) { |
|
$ActiveConnections{$Socket}->cancel; |
delete($ActiveConnections{$Socket}); |
delete($ActiveConnections{$Socket}); |
$ConnectionCount--; |
$ConnectionCount--; |
if ($ConnectionCount < 0) { $ConnectionCount = 0; } |
if ($ConnectionCount < 0) { $ConnectionCount = 0; } |
Line 762 sub KillSocket {
|
Line 772 sub KillSocket {
|
# work queue, the work all gets failed with con_lost. |
# work queue, the work all gets failed with con_lost. |
# |
# |
if($ConnectionCount == 0) { |
if($ConnectionCount == 0) { |
|
$LondConnecting = 0; # No connections so also not connecting. |
EmptyQueue(); |
EmptyQueue(); |
CloseAllLondConnections; # Should all already be closed but... |
CloseAllLondConnections; # Should all already be closed but... |
} |
} |
|
UpdateStatus(); |
} |
} |
|
|
=pod |
=pod |
Line 776 is readable. The action is state depend
|
Line 788 is readable. The action is state depend
|
|
|
=head3 State=Initialized |
=head3 State=Initialized |
|
|
We''re waiting for the challenge, this is a no-op until the |
We are waiting for the challenge, this is a no-op until the |
state changes. |
state changes. |
|
|
=head3 State=Challenged |
=head3 State=Challenged |
Line 786 The connection must echo the challenge b
|
Line 798 The connection must echo the challenge b
|
|
|
=head3 State=ChallengeReplied |
=head3 State=ChallengeReplied |
|
|
The challenge has been replied to. The we are receiveing the |
The challenge has been replied to. Then we are receiving the |
'ok' from the partner. |
'ok' from the partner. |
|
|
=head3 State=ReadingVersionString |
=head3 State=ReadingVersionString |
Line 812 The the key has been requested, now we a
|
Line 824 The the key has been requested, now we a
|
=head3 State=Idle |
=head3 State=Idle |
|
|
The encryption key has been negotiated or we have finished |
The encryption key has been negotiated or we have finished |
reading data from the a transaction. If the callback data has |
reading data from the a transaction. If the callback data have |
a client as well as the socket iformation, then we are |
a client as well as the socket information, then we are |
doing a transaction and the data received is relayed to the client |
doing a transaction and the data received are relayed to the client |
before the socket is put on the idle list. |
before the socket is put on the idle list. |
|
|
=head3 State=SendingRequest |
=head3 State=SendingRequest |
Line 831 to readable to receive the reply.
|
Line 843 to readable to receive the reply.
|
The parameter to this function are: |
The parameter to this function are: |
|
|
The event. Implicit in this is the watcher and its data. The data |
The event. Implicit in this is the watcher and its data. The data |
contains at least the lond connection object and, if a |
contain at least the lond connection object and, if a |
transaction is in progress, the socket attached to the local client. |
transaction is in progress, the socket attached to the local client. |
|
|
=cut |
=cut |
Line 936 sub LondReadable {
|
Line 948 sub LondReadable {
|
CompleteTransaction($Socket, |
CompleteTransaction($Socket, |
$ActiveTransactions{$Socket}); |
$ActiveTransactions{$Socket}); |
} else { |
} else { |
Log("SUCCESS", "Connection ".$ConnectionCount." to " |
my $count = $Socket->GetClientData(); |
|
Log("SUCCESS", "Connection ".$count." to " |
.$RemoteHost." now ready for action"); |
.$RemoteHost." now ready for action"); |
} |
} |
ServerToIdle($Socket); # Next work unit or idle. |
ServerToIdle($Socket); # Next work unit or idle. |
Line 973 event. The action taken is very state d
|
Line 986 event. The action taken is very state d
|
=head3 State = Connected |
=head3 State = Connected |
|
|
The connection is in the process of sending the 'init' hailing to the |
The connection is in the process of sending the 'init' hailing to the |
lond on the remote end. The connection object''s Writable member is |
lond on the remote end. The Writable member of the connection object |
called. On error, ConnectionError is called to destroy the connection |
is called. On error, call ConnectionError to destroy the connection |
and remove it from the ActiveConnections hash |
and remove it from the ActiveConnections hash. |
|
|
=head3 Initialized |
=head3 Initialized |
|
|
Line 1161 sub QueueDelayed {
|
Line 1174 sub QueueDelayed {
|
Debug(4, "Delayed path: ".$path); |
Debug(4, "Delayed path: ".$path); |
opendir(DIRHANDLE, $path); |
opendir(DIRHANDLE, $path); |
|
|
use Apache::lonnet; |
my $host_id_re = '(?:'.join('|',map {quotemeta($_)} (@all_host_ids)).')'; |
my @all_host_ids = &Apache::lonnet::machine_ids($RemoteHost); |
|
|
|
my $host_id_re = '(?:'.join('|',@all_host_ids).')'; |
|
my @alldelayed = grep(/\.$host_id_re$/, readdir(DIRHANDLE)); |
my @alldelayed = grep(/\.$host_id_re$/, readdir(DIRHANDLE)); |
closedir(DIRHANDLE); |
closedir(DIRHANDLE); |
foreach my $dfname (sort(@alldelayed)) { |
foreach my $dfname (sort(@alldelayed)) { |
Line 1187 sub QueueDelayed {
|
Line 1197 sub QueueDelayed {
|
=head2 MakeLondConnection |
=head2 MakeLondConnection |
|
|
Create a new lond connection object, and start it towards its initial |
Create a new lond connection object, and start it towards its initial |
idleness. Once idle, it becomes elligible to receive transactions |
idleness. Once idle, it becomes eligible to receive transactions |
from the work queue. If the work queue is not empty when the |
from the work queue. If the work queue is not empty when the |
connection is completed and becomes idle, it will dequeue an entry and |
connection is completed and becomes idle, it will dequeue an entry and |
start off on it. |
start off on it. |
Line 1202 sub MakeLondConnection {
|
Line 1212 sub MakeLondConnection {
|
&GetServerPort(), |
&GetServerPort(), |
&GetHostId()); |
&GetHostId()); |
|
|
if($Connection eq undef) { # Needs to be more robust later. |
if($Connection eq undef) { |
Log("CRITICAL","Failed to make a connection with lond."); |
Log("CRITICAL","Failed to make a connection with lond."); |
$ConnectionRetriesLeft--; |
$ConnectionRetriesLeft--; |
return 0; # Failure. |
return 0; # Failure. |
} else { |
} else { |
|
|
|
$LondConnecting = 1; # Connection in progress. |
# The connection needs to have writability |
# The connection needs to have writability |
# monitored in order to send the init sequence |
# monitored in order to send the init sequence |
# that starts the whole authentication/key |
# that starts the whole authentication/key |
Line 1232 sub MakeLondConnection {
|
Line 1243 sub MakeLondConnection {
|
&SetupTimer; # Need to handle timeouts with connections... |
&SetupTimer; # Need to handle timeouts with connections... |
} |
} |
$ConnectionCount++; |
$ConnectionCount++; |
|
$Connection->SetClientData($ConnectionCount); |
Debug(4, "Connection count = ".$ConnectionCount); |
Debug(4, "Connection count = ".$ConnectionCount); |
if($ConnectionCount == 1) { # First Connection: |
if($ConnectionCount == 1) { # First Connection: |
QueueDelayed; |
QueueDelayed; |
} |
} |
Log("SUCESS", "Created connection ".$ConnectionCount |
Log("SUCCESS", "Created connection ".$ConnectionCount |
." to host ".GetServerHost()); |
." to host ".GetServerHost()); |
$LondConnecting = 1; # Connection in progress. |
|
return 1; # Return success. |
return 1; # Return success. |
} |
} |
|
|
Line 1258 reply.
|
Line 1269 reply.
|
|
|
=item $Client |
=item $Client |
|
|
Connection to the client that is making this request We got the |
Connection to the client that is making this request. We got the |
request from this socket, and when the request has been relayed to |
request from this socket, and when the request has been relayed to |
lond and we get a reply back from lond it will get sent to this |
lond and we get a reply back from lond it will get sent to this |
socket. |
socket. |
Line 1344 sub QueueTransaction {
|
Line 1355 sub QueueTransaction {
|
} |
} |
} |
} |
|
|
#-------------------------- Lonc UNIX socket handling --------------------- |
#-------------------------- Lonc UNIX socket handling ------------------- |
|
|
=pod |
=pod |
|
|
=head2 ClientRequest |
=head2 ClientRequest |
|
|
Callback that is called when data can be read from the UNIX domain |
Callback that is called when data can be read from the UNIX domain |
socket connecting us with an apache server process. |
socket connecting us with an apache server process. |
|
|
Line 1379 sub ClientRequest {
|
Line 1390 sub ClientRequest {
|
$data = $data.$thisread; # Append new data. |
$data = $data.$thisread; # Append new data. |
$watcher->data($data); |
$watcher->data($data); |
if($data =~ /\n$/) { # Request entirely read. |
if($data =~ /\n$/) { # Request entirely read. |
if($data eq "close_connection_exit\n") { |
if ($data eq "close_connection_exit\n") { |
Log("CRITICAL", |
Log("CRITICAL", |
"Request Close Connection ... exiting"); |
"Request Close Connection ... exiting"); |
CloseAllLondConnections(); |
CloseAllLondConnections(); |
exit; |
exit; |
|
} elsif ($data eq "reset_retries\n") { |
|
Log("INFO", "Resetting Connection Retries."); |
|
$ConnectionRetriesLeft = $ConnectionRetries; |
|
&UpdateStatus(); |
|
my $Transaction = LondTransaction->new($data); |
|
$Transaction->SetClient($socket); |
|
StartClientReply($Transaction, "ok\n"); |
|
$watcher->cancel(); |
|
return; |
} |
} |
Debug(8, "Complete transaction received: ".$data); |
Debug(8, "Complete transaction received: ".$data); |
if($LogTransactions) { |
if ($LogTransactions) { |
Log("SUCCESS", "Transaction: '$data'"); # Transaction has \n. |
Log("SUCCESS", "Transaction: '$data'"); # Transaction has \n. |
} |
} |
my $Transaction = LondTransaction->new($data); |
my $Transaction = LondTransaction->new($data); |
Line 1439 sub accept_client {
|
Line 1459 sub accept_client {
|
Callback that is called when a connection is received on the unix |
Callback that is called when a connection is received on the unix |
socket for a new client of lonc. The callback is parameterized by the |
socket for a new client of lonc. The callback is parameterized by the |
event.. which is a-priori assumed to be an io event, and therefore has |
event.. which is a-priori assumed to be an io event, and therefore has |
an fd member that is the Listener socket. We Accept the connection |
an fd member that is the Listener socket. We accept the connection |
and register a new event on the readability of that socket: |
and register a new event on the readability of that socket: |
|
|
=cut |
=cut |
Line 1519 sub GetServerPort {
|
Line 1539 sub GetServerPort {
|
Setup a lonc listener event. The event is called when the socket |
Setup a lonc listener event. The event is called when the socket |
becomes readable.. that corresponds to the receipt of a new |
becomes readable.. that corresponds to the receipt of a new |
connection. The event handler established will accept the connection |
connection. The event handler established will accept the connection |
(creating a communcations channel), that int turn will establish |
(creating a communications channel), that in turn will establish |
another event handler to subess requests. |
another event handler to subess requests. |
|
|
=head2 Parameters: |
=head2 Parameters: |
Line 1659 sub ToggleDebug {
|
Line 1679 sub ToggleDebug {
|
|
|
This sub implements a child process for a single lonc daemon. |
This sub implements a child process for a single lonc daemon. |
Optional parameter: |
Optional parameter: |
$socket - if provided, this is a socket already open for listen |
$socket - if provided, this is a socket already open for listening |
on the client socket. Otherwise, a new listen is set up. |
on the client socket. Otherwise, a new listener is set up. |
|
|
=cut |
=cut |
|
|
Line 1717 sub ChildProcess {
|
Line 1737 sub ChildProcess {
|
cb => \&ToggleDebug, |
cb => \&ToggleDebug, |
data => "INT"); |
data => "INT"); |
|
|
|
# Block the pipe signal we'll get when the socket disconnects. We detect |
|
# socket disconnection via send/receive failures. On disconnect, the |
|
# socket becomes readable .. which will force the disconnect detection. |
|
|
|
my $set = POSIX::SigSet->new(SIGPIPE); |
|
sigprocmask(SIG_BLOCK, $set); |
|
|
# Figure out if we got passed a socket or need to open one to listen for |
# Figure out if we got passed a socket or need to open one to listen for |
# client requests. |
# client requests. |
|
|
Line 1760 sub CreateChild {
|
Line 1787 sub CreateChild {
|
my $sigset = POSIX::SigSet->new(SIGINT); |
my $sigset = POSIX::SigSet->new(SIGINT); |
sigprocmask(SIG_BLOCK, $sigset); |
sigprocmask(SIG_BLOCK, $sigset); |
$RemoteHost = $host; |
$RemoteHost = $host; |
|
ShowStatus('Parent keeping the flock'); # Update time in status message. |
Log("CRITICAL", "Forking server for ".$host); |
Log("CRITICAL", "Forking server for ".$host); |
my $pid = fork; |
my $pid = fork; |
if($pid) { # Parent |
if($pid) { # Parent |
$RemoteHost = "Parent"; |
$RemoteHost = "Parent"; |
$ChildHash{$pid} = $host; |
$ChildPid{$pid} = $host; |
sigprocmask(SIG_UNBLOCK, $sigset); |
sigprocmask(SIG_UNBLOCK, $sigset); |
|
undef(@all_host_ids); |
} else { # child. |
} else { # child. |
$RemoteHostId = $hostid; |
$RemoteHostId = $hostid; |
ShowStatus("Connected to ".$RemoteHost); |
ShowStatus("Connected to ".$RemoteHost); |
Line 1809 sub parent_client_connection {
|
Line 1837 sub parent_client_connection {
|
} |
} |
|
|
sub get_remote_hostname { |
sub get_remote_hostname { |
my ($event) = @_; |
my ($event) = @_; |
my $watcher = $event->w; |
my $watcher = $event->w; |
my $socket = $watcher->fd; |
my $socket = $watcher->fd; |
|
|
my $thisread; |
|
my $rv = $socket->recv($thisread, POSIX::BUFSIZ, 0); |
|
Debug(8, "rcv: data length = ".length($thisread)." read =".$thisread); |
|
if (!defined($rv) || length($thisread) == 0) { |
|
# Likely eof on socket. |
|
Debug(5,"Client Socket closed on lonc for p_c_c"); |
|
close($socket); |
|
$watcher->cancel(); |
|
return; |
|
} |
|
|
|
my $data = $watcher->data().$thisread; |
my $thisread; |
$watcher->data($data); |
my $rv = $socket->recv($thisread, POSIX::BUFSIZ, 0); |
if($data =~ /\n$/) { # Request entirely read. |
Debug(8, "rcv: data length = ".length($thisread)." read =".$thisread); |
chomp($data); |
if (!defined($rv) || length($thisread) == 0) { |
} else { |
# Likely eof on socket. |
return; |
Debug(5,"Client Socket closed on lonc for p_c_c"); |
} |
close($socket); |
|
$watcher->cancel(); |
&Debug(5,"Creating child for $data (parent_client_connection)"); |
return; |
my ($hostname,$lonid) = split(':',$data,2); |
} |
|
|
|
my $data = $watcher->data().$thisread; |
|
$watcher->data($data); |
|
if($data =~ /\n$/) { # Request entirely read. |
|
chomp($data); |
|
} else { |
|
return; |
|
} |
|
|
|
&Debug(5,"Creating child for $data (parent_client_connection)"); |
|
(my $hostname,my $lonid,@all_host_ids) = split(':',$data); |
|
$ChildHost{$hostname}++; |
|
if ($ChildHost{$hostname} == 1) { |
&CreateChild($hostname,$lonid); |
&CreateChild($hostname,$lonid); |
|
} else { |
# Clean up the listen since now the child takes over until it exits. |
&Log('WARNING',"Request for a second child on $hostname"); |
$watcher->cancel(); # Nolonger listening to this event |
} |
$socket->send("done\n"); |
# Clean up the listen since now the child takes over until it exits. |
$socket->close(); |
$watcher->cancel(); # Nolonger listening to this event |
|
$socket->send("done\n"); |
|
$socket->close(); |
} |
} |
|
|
# parent_listen: |
# parent_listen: |
Line 1890 sub parent_listen {
|
Line 1922 sub parent_listen {
|
|
|
sub parent_clean_up { |
sub parent_clean_up { |
my ($loncapa_host) = @_; |
my ($loncapa_host) = @_; |
Debug(5, "parent_clean_up: $loncapa_host"); |
Debug(1, "parent_clean_up: $loncapa_host"); |
|
|
my $socket_file = &GetLoncSocketPath($loncapa_host); |
my $socket_file = &GetLoncSocketPath($loncapa_host); |
unlink($socket_file); # No problem if it doesn't exist yet [startup e.g.] |
unlink($socket_file); # No problem if it doesn't exist yet [startup e.g.] |
Line 1899 sub parent_clean_up {
|
Line 1931 sub parent_clean_up {
|
} |
} |
|
|
|
|
# listen_on_all_unix_sockets: |
|
# This sub initiates a listen on all unix domain lonc client sockets. |
# This sub initiates a listen on the common unix domain lonc client socket. |
# This will be called in the case where we are trimming idle processes. |
# loncnew starts up with no children, and only spawns off children when a |
# When idle processes are trimmed, loncnew starts up with no children, |
# connection request occurs on the common client unix socket. The spawned |
# and only spawns off children when a connection request occurs on the |
# child continues to run until it has been idle a while at which point it |
# client unix socket. The spawned child continues to run until it has |
# eventually exits and once more the parent picks up the listen. |
# been idle a while at which point it eventually exits and once more |
|
# the parent picks up the listen. |
|
# |
# |
# Parameters: |
# Parameters: |
# NONE |
# NONE |
Line 1915 sub parent_clean_up {
|
Line 1945 sub parent_clean_up {
|
# Returns: |
# Returns: |
# NONE |
# NONE |
# |
# |
sub listen_on_all_unix_sockets { |
|
Debug(5, "listen_on_all_unix_sockets"); |
|
my $host_iterator = &LondConnection::GetHostIterator(); |
|
while (!$host_iterator->end()) { |
|
my $host_entry_ref = $host_iterator->get(); |
|
my $host_name = $host_entry_ref->[3]; |
|
Debug(9, "Listen for $host_name"); |
|
&parent_listen($host_name); |
|
$host_iterator->next(); |
|
} |
|
} |
|
|
|
sub listen_on_common_socket { |
sub listen_on_common_socket { |
Debug(5, "listen_on_common_socket"); |
Debug(5, "listen_on_common_socket"); |
&parent_listen(); |
&parent_listen(); |
Line 1951 sub server_died {
|
Line 1969 sub server_died {
|
} |
} |
# need the host to restart: |
# need the host to restart: |
|
|
my $host = $ChildHash{$pid}; |
my $host = $ChildPid{$pid}; |
if($host) { # It's for real... |
if($host) { # It's for real... |
&Debug(9, "Caught sigchild for $host"); |
&Debug(9, "Caught sigchild for $host"); |
delete($ChildHash{$pid}); |
delete($ChildPid{$pid}); |
|
delete($ChildHost{$host}); |
&parent_clean_up($host); |
&parent_clean_up($host); |
|
|
} else { |
} else { |
Line 2061 die "Main Event loop exited: $ret";
|
Line 2080 die "Main Event loop exited: $ret";
|
=head1 CheckKids |
=head1 CheckKids |
|
|
Since kids do not die as easily in this implementation |
Since kids do not die as easily in this implementation |
as the previous one, there is no need to restart the |
as the previous one, there is no need to restart the |
dead ones (all dead kids get restarted when they die!!) |
dead ones (all dead kids get restarted when they die!!) |
The only thing this function does is to pass USR1 to the |
The only thing this function does is to pass USR1 to the |
kids so that they report their status. |
kids so that they report their status. |
Line 2078 sub CheckKids {
|
Line 2097 sub CheckKids {
|
foreach my $host (keys %parent_dispatchers) { |
foreach my $host (keys %parent_dispatchers) { |
print $fh "LONC Parent process listening for $host\n"; |
print $fh "LONC Parent process listening for $host\n"; |
} |
} |
foreach my $pid (keys %ChildHash) { |
foreach my $pid (keys %ChildPid) { |
Debug(2, "Sending USR1 -> $pid"); |
Debug(2, "Sending USR1 -> $pid"); |
kill 'USR1' => $pid; # Tell Child to report status. |
kill 'USR1' => $pid; # Tell Child to report status. |
} |
} |
Line 2123 sub UpdateKids {
|
Line 2142 sub UpdateKids {
|
# (lost unless they are critical). |
# (lost unless they are critical). |
|
|
&KillThemAll(); |
&KillThemAll(); |
|
LondConnection->ResetReadConfig(); |
} |
} |
|
|
|
|
Line 2131 sub UpdateKids {
|
Line 2151 sub UpdateKids {
|
=head1 Restart |
=head1 Restart |
|
|
Signal handler for HUP... all children are killed and |
Signal handler for HUP... all children are killed and |
we self restart. This is an el-cheapo way to re read |
we self restart. This is an el-cheapo way to re-read |
the config file. |
the config file. |
|
|
=cut |
=cut |
|
|
sub Restart { |
sub Restart { |
&KillThemAll; # First kill all the children. |
&KillThemAll; # First kill all the children. |
|
LondConnection->ResetReadConfig(); |
Log("CRITICAL", "Restarting"); |
Log("CRITICAL", "Restarting"); |
my $execdir = $perlvar{'lonDaemons'}; |
my $execdir = $perlvar{'lonDaemons'}; |
unlink("$execdir/logs/lonc.pid"); |
unlink("$execdir/logs/lonc.pid"); |
Line 2155 SIGHUP. Responds to sigint and sigterm.
|
Line 2176 SIGHUP. Responds to sigint and sigterm.
|
|
|
sub KillThemAll { |
sub KillThemAll { |
Debug(2, "Kill them all!!"); |
Debug(2, "Kill them all!!"); |
local($SIG{CHLD}) = 'IGNORE'; # Our children >will< die. |
|
foreach my $pid (keys %ChildHash) { |
#local($SIG{CHLD}) = 'IGNORE'; |
my $serving = $ChildHash{$pid}; |
# Our children >will< die. |
|
# but we need to catch their death and cleanup after them in case this is |
|
# a restart set of kills |
|
my @allpids = keys(%ChildPid); |
|
foreach my $pid (@allpids) { |
|
my $serving = $ChildPid{$pid}; |
ShowStatus("Nicely Killing lonc for $serving pid = $pid"); |
ShowStatus("Nicely Killing lonc for $serving pid = $pid"); |
Log("CRITICAL", "Nicely Killing lonc for $serving pid = $pid"); |
Log("CRITICAL", "Nicely Killing lonc for $serving pid = $pid"); |
kill 'QUIT' => $pid; |
kill 'QUIT' => $pid; |
} |
} |
|
ShowStatus("Finished killing child processes off."); |
} |
} |
|
|
|
|
Line 2173 sub really_kill_them_all_dammit
|
Line 2200 sub really_kill_them_all_dammit
|
{ |
{ |
Debug(2, "Kill them all Dammit"); |
Debug(2, "Kill them all Dammit"); |
local($SIG{CHLD} = 'IGNORE'); # In case some purist reenabled them. |
local($SIG{CHLD} = 'IGNORE'); # In case some purist reenabled them. |
foreach my $pid (keys %ChildHash) { |
foreach my $pid (keys %ChildPid) { |
my $serving = $ChildHash{$pid}; |
my $serving = $ChildPid{$pid}; |
&ShowStatus("Nastily killing lonc for $serving pid = $pid"); |
&ShowStatus("Nastily killing lonc for $serving pid = $pid"); |
Log("CRITICAL", "Nastily killing lonc for $serving pid = $pid"); |
Log("CRITICAL", "Nastily killing lonc for $serving pid = $pid"); |
kill 'KILL' => $pid; |
kill 'KILL' => $pid; |
delete($ChildHash{$pid}); |
delete($ChildPid{$pid}); |
my $execdir = $perlvar{'lonDaemons'}; |
my $execdir = $perlvar{'lonDaemons'}; |
unlink("$execdir/logs/lonc.pid"); |
unlink("$execdir/logs/lonc.pid"); |
} |
} |
Line 2255 A hash of lond connections that have no
|
Line 2282 A hash of lond connections that have no
|
can be closed if they are idle for a long enough time. |
can be closed if they are idle for a long enough time. |
|
|
=cut |
=cut |
|
|
|
=pod |
|
|
|
=head1 Log messages |
|
|
|
The following is a list of log messages that can appear in the |
|
lonc.log file. Each log file has a severity and a message. |
|
|
|
=over 2 |
|
|
|
=item Warning A socket timeout was detected |
|
|
|
If there are pending transactions in the socket's queue, |
|
they are failed (saved if critical). If the connection |
|
retry count gets exceeded by this, the |
|
remote host is marked as dead. |
|
Called when timeouts occurred during the connection and |
|
connection dialog with a remote host. |
|
|
|
=item Critical Host makred DEAD <hostname> |
|
|
|
The numer of retry counts for contacting a host was |
|
exceeded. The host is marked dead an no |
|
further attempts will be made by that child. |
|
|
|
=item Info lonc pipe client hung up on us |
|
|
|
Write to the client pipe indicated no data transferred |
|
Socket to remote host is shut down. Reply to the client |
|
is discarded. Note: This is commented out in &ClientWriteable |
|
|
|
=item Success Reply from lond: <data> |
|
|
|
Can be enabled for debugging by setting LogTransactions to nonzero. |
|
Indicates a successful transaction with lond, <data> is the data received |
|
from the remote lond. |
|
|
|
=item Success A delayed transaction was completed |
|
|
|
A transaction that must be reliable was executed and completed |
|
as lonc restarted. This is followed by a mesage of the form |
|
|
|
S: client-name : request |
|
|
|
=item WARNING Failing transaction <cmd>:<subcmd> |
|
|
|
Transaction failed on a socket, but the failure retry count for the remote |
|
node has not yet been exhausted (the node is not yet marked dead). |
|
cmd is the command, subcmd is the subcommand. This results from a con_lost |
|
when communicating with lond. |
|
|
|
=item WARNING Shutting down a socket |
|
|
|
Called when a socket is being closed to lond. This is emitted both when |
|
idle pruning is being done and when the socket has been disconnected by the remote. |
|
|
|
=item WARNING Lond connection lost. |
|
|
|
Called when a read from lond's socket failed indicating lond has closed the |
|
connection or died. This should be followed by one or more |
|
|
|
"WARNING Failing transaction..." msgs for each in-flight or queued transaction. |
|
|
|
=item INFO Connected to lond version: <version> |
|
|
|
When connection negotiation is complete, the lond version is requested and logged here. |
|
|
|
=item SUCCESS Connection n to host now ready for action |
|
|
|
Emitted when connection has been completed with lond. n is then number of |
|
concurrent connections and host, the host to which the connection has just |
|
been established. |
|
|
|
=item WARNING Connection to host has been disconnected |
|
|
|
Write to a lond resulted in failure status. Connection to lond is dropped. |
|
|
|
=item SUCCESS Created connection n to host host |
|
|
|
Initial connection request to host..(before negotiation). |
|
|
|
=item CRITICAL Request Close Connection ... exiting |
|
|
|
Client has sent "close_connection_exit" The loncnew server is exiting. |
|
|
|
=item INFO Resetting Connection Retries |
|
|
|
Client has sent "reset_retries" The lond connection retries are reset to zero for the |
|
corresponding lond. |
|
|
|
=item SUCCESS Transaction <data> |
|
|
|
Only emitted if the global variable $LogTransactions was set to true. |
|
A client has requested a lond transaction <data> is the contents of the request. |
|
|
|
=item SUCCESS Toggled transaction logging <LogTransactions> |
|
|
|
The state of the $LogTransactions global has been toggled, and its current value |
|
(after being toggled) is displayed. When non zero additional logging of transactions |
|
is enabled for debugging purposes. Transaction logging is toggled on receipt of a USR2 |
|
signal. |
|
|
|
=item CRITICAL Abnormal exit. Child <pid> for <host> died thorugh signal. |
|
|
|
QUIT signal received. lonc child process is exiting. |
|
|
|
=item SUCCESS New debugging level for <RemoteHost> now <DebugLevel> |
|
|
|
Debugging toggled for the host loncnew is talking with. |
|
Currently debugging is a level based scheme with higher number |
|
conveying more information. The daemon starts out at |
|
DebugLevel 0 and can toggle back and forth between that and |
|
DebugLevel 2 These are controlled by |
|
the global variables $DebugLevel and $NextDebugLevel |
|
The debug level can go up to 9. |
|
SIGINT toggles the debug level. The higher the debug level the |
|
more debugging information is spewed. See the Debug |
|
sub in loncnew. |
|
|
|
=item CRITICAL Forking server for host |
|
|
|
A child is being created to service requests for the specified host. |
|
|
|
|
|
=item WARNING Request for a second child on hostname |
|
|
|
Somehow loncnew was asked to start a second child on a host that already had a child |
|
servicing it. This request is not honored, but themessage is emitted. This could happen |
|
due to a race condition. When a client attempts to contact loncnew for a new host, a child |
|
is forked off to handle the requests for that server. The parent then backs off the Unix |
|
domain socket leaving it for the child to service all requests. If in the time between |
|
creating the child, and backing off, a new connection request comes in to the unix domain |
|
socket, this could trigger (unlikely but remotely possible),. |
|
|
|
=item CRITICAL ------ Starting Children ---- |
|
|
|
This message should probably be changed to "Entering event loop" as the loncnew only starts |
|
children as needed. This message is emitted as new events are established and |
|
the event processing loop is entered. |
|
|
|
=item INFO Updating connections via SIGUSR2 |
|
|
|
SIGUSR2 received. The original code would kill all clients, re-read the host file, |
|
then restart children for each host. Now that children are started on demand, this |
|
just kills all child processes and lets requests start them as needed again. |
|
|
|
|
|
=item CRITICAL Restarting |
|
|
|
SigHUP received. all the children are killed and the script exec's itself to start again. |
|
|
|
=item CRITICAL Nicely killing lonc for host pid = <pid> |
|
|
|
Attempting to kill the child that is serving the specified host (pid given) cleanly via |
|
SIGQUIT. The child should handle that, clean up nicely and exit. |
|
|
|
=item CRITICAL Nastily killing lonc for host pid = <pid> |
|
|
|
The child specified did not die when requested via SIGQUIT. Therefore it is killed |
|
via SIGKILL. |
|
|
|
=item CRITICAL Asked to kill children.. first be nice.. |
|
|
|
In the parent's INT handler. INT kills the child processes. This inidicate loncnew |
|
is about to attempt to kill all known children via SIGQUIT. This message should be followed |
|
by one "Nicely killing" message for each extant child. |
|
|
|
=item CRITICAL Now kill children nasty |
|
|
|
In the parent's INT handler. remaining children are about to be killed via |
|
SIGKILL. Should be followed by a Nastily killing... for each lonc child that |
|
refused to die. |
|
|
|
=item CRITICAL Master process exiting |
|
|
|
In the parent's INT handler. just prior to the exit 0 call. |
|
|
|
=back |
|
|
|
=cut |