--- loncom/loncnew 2008/10/06 10:55:46 1.88 +++ loncom/loncnew 2020/01/12 01:55:44 1.100.10.2 @@ -2,7 +2,7 @@ # The LearningOnline Network with CAPA # lonc maintains the connections to remote computers # -# $Id: loncnew,v 1.88 2008/10/06 10:55:46 foxr Exp $ +# $Id: loncnew,v 1.100.10.2 2020/01/12 01:55:44 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -26,7 +26,7 @@ # 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. # Development iterations: # - Setup basic event loop. (done) @@ -85,7 +85,7 @@ my $ClientConnection = 0; # Uniquifier f my $DebugLevel = 0; 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 $executable = $0; # Get the full path to me. @@ -349,7 +349,7 @@ sub child_exit { =head2 Tick -Invoked each timer tick. +Invoked each timer tick. =cut @@ -441,7 +441,8 @@ Trigger disconnections of idle sockets. sub SetupTimer { Debug(6, "SetupTimer"); - Event->timer(interval => 1, cb => \&Tick ); + Event->timer(interval => 1, cb => \&Tick, + hard => 1); } =pod @@ -487,8 +488,8 @@ sub ServerToIdle { Event callback for when a client socket is writable. -This callback is established when a transaction reponse is -avaiable from lond. The response is forwarded to the unix socket +This callback is established when a transaction response is +available from lond. The response is forwarded to the unix socket as it becomes writable in this sub. Parameters: @@ -558,7 +559,8 @@ sub ClientWritable { if($errno == POSIX::EWOULDBLOCK || $errno == POSIX::EAGAIN || $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. &Debug(5,"ClientWritable error or peer shutdown".$RemoteHost); $Watcher->cancel; # Stop the watcher. @@ -587,8 +589,8 @@ Parameters: =item Socket -Socket on which the lond transaction occured. This is a -LondConnection. The data received is in the TransactionReply member. +Socket on which the lond transaction occurred. This is a +LondConnection. The data received are in the TransactionReply member. =item Transaction @@ -628,7 +630,7 @@ sub CompleteTransaction { =item data - The data to send to apached client. + The data to send to apache client. =cut @@ -741,7 +743,7 @@ Parameters: =item Restart -nonzero if we are allowed to create a new connection. +non-zero if we are allowed to create a new connection. =cut @@ -761,6 +763,7 @@ sub KillSocket { delete ($ActiveTransactions{$Socket}); } if(exists($ActiveConnections{$Socket})) { + $ActiveConnections{$Socket}->cancel; delete($ActiveConnections{$Socket}); $ConnectionCount--; if ($ConnectionCount < 0) { $ConnectionCount = 0; } @@ -769,9 +772,11 @@ sub KillSocket { # work queue, the work all gets failed with con_lost. # if($ConnectionCount == 0) { + $LondConnecting = 0; # No connections so also not connecting. EmptyQueue(); CloseAllLondConnections; # Should all already be closed but... } + UpdateStatus(); } =pod @@ -783,7 +788,7 @@ is readable. The action is state depend =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. =head3 State=Challenged @@ -793,7 +798,7 @@ The connection must echo the challenge b =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. =head3 State=ReadingVersionString @@ -819,9 +824,9 @@ The the key has been requested, now we a =head3 State=Idle The encryption key has been negotiated or we have finished -reading data from the a transaction. If the callback data has -a client as well as the socket iformation, then we are -doing a transaction and the data received is relayed to the client +reading data from the a transaction. If the callback data have +a client as well as the socket information, then we are +doing a transaction and the data received are relayed to the client before the socket is put on the idle list. =head3 State=SendingRequest @@ -838,7 +843,7 @@ to readable to receive the reply. The parameter to this function are: 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. =cut @@ -943,7 +948,8 @@ sub LondReadable { CompleteTransaction($Socket, $ActiveTransactions{$Socket}); } else { - Log("SUCCESS", "Connection ".$ConnectionCount." to " + my $count = $Socket->GetClientData(); + Log("SUCCESS", "Connection ".$count." to " .$RemoteHost." now ready for action"); } ServerToIdle($Socket); # Next work unit or idle. @@ -980,9 +986,9 @@ event. The action taken is very state d =head3 State = Connected 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 -called. On error, ConnectionError is called to destroy the connection -and remove it from the ActiveConnections hash +lond on the remote end. The Writable member of the connection object +is called. On error, call ConnectionError to destroy the connection +and remove it from the ActiveConnections hash. =head3 Initialized @@ -1191,7 +1197,7 @@ sub QueueDelayed { =head2 MakeLondConnection 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 connection is completed and becomes idle, it will dequeue an entry and start off on it. @@ -1206,7 +1212,7 @@ sub MakeLondConnection { &GetServerPort(), &GetHostId()); - if($Connection eq undef) { # Needs to be more robust later. + if($Connection eq undef) { Log("CRITICAL","Failed to make a connection with lond."); $ConnectionRetriesLeft--; return 0; # Failure. @@ -1237,11 +1243,12 @@ sub MakeLondConnection { &SetupTimer; # Need to handle timeouts with connections... } $ConnectionCount++; + $Connection->SetClientData($ConnectionCount); Debug(4, "Connection count = ".$ConnectionCount); if($ConnectionCount == 1) { # First Connection: QueueDelayed; } - Log("SUCESS", "Created connection ".$ConnectionCount + Log("SUCCESS", "Created connection ".$ConnectionCount ." to host ".GetServerHost()); return 1; # Return success. } @@ -1262,7 +1269,7 @@ reply. =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 lond and we get a reply back from lond it will get sent to this socket. @@ -1348,11 +1355,11 @@ sub QueueTransaction { } } -#-------------------------- Lonc UNIX socket handling --------------------- - +#-------------------------- Lonc UNIX socket handling ------------------- =pod =head2 ClientRequest + Callback that is called when data can be read from the UNIX domain socket connecting us with an apache server process. @@ -1452,7 +1459,7 @@ sub accept_client { 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 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: =cut @@ -1532,7 +1539,7 @@ sub GetServerPort { Setup a lonc listener event. The event is called when the socket becomes readable.. that corresponds to the receipt of a new 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. =head2 Parameters: @@ -1672,8 +1679,8 @@ sub ToggleDebug { This sub implements a child process for a single lonc daemon. Optional parameter: - $socket - if provided, this is a socket already open for listen - on the client socket. Otherwise, a new listen is set up. + $socket - if provided, this is a socket already open for listening + on the client socket. Otherwise, a new listener is set up. =cut @@ -1730,6 +1737,13 @@ sub ChildProcess { cb => \&ToggleDebug, 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 # client requests. @@ -1773,6 +1787,7 @@ sub CreateChild { my $sigset = POSIX::SigSet->new(SIGINT); sigprocmask(SIG_BLOCK, $sigset); $RemoteHost = $host; + ShowStatus('Parent keeping the flock'); # Update time in status message. Log("CRITICAL", "Forking server for ".$host); my $pid = fork; if($pid) { # Parent @@ -2065,7 +2080,7 @@ die "Main Event loop exited: $ret"; =head1 CheckKids 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!!) The only thing this function does is to pass USR1 to the kids so that they report their status. @@ -2135,7 +2150,7 @@ sub UpdateKids { =head1 Restart 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. =cut @@ -2218,8 +2233,8 @@ sub Terminate { } sub my_hostname { - use Sys::Hostname; - my $name = &hostname(); + use Sys::Hostname::FQDN(); + my $name = Sys::Hostname::FQDN::fqdn(); &Debug(9,"Name is $name"); return $name; } @@ -2281,7 +2296,7 @@ If there are pending transactions in the 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 occured during the connection and +Called when timeouts occurred during the connection and connection dialog with a remote host. =item Critical Host makred DEAD @@ -2408,7 +2423,7 @@ 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 childrean aree started on demand, this +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. @@ -2419,7 +2434,7 @@ SigHUP received. all the children are k =item CRITICAL Nicely killing lonc for host 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. +SIGQUIT. The child should handle that, clean up nicely and exit. =item CRITICAL Nastily killing lonc for host pid =