Diff for /loncom/loncnew between versions 1.90 and 1.107

version 1.90, 2010/12/20 11:15:51 version 1.107, 2018/12/10 17:34:22
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 74  my %perlvar    = %{$perlvarref}; Line 74  my %perlvar    = %{$perlvarref};
   
 my %ChildPid; # by pid -> host.  my %ChildPid; # by pid -> host.
 my %ChildHost; # by host.  my %ChildHost; # by host.
   my %ChildKeyMode;               # by pid -> keymode
 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 85  my $ClientConnection = 0; # Uniquifier f Line 86  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= 7200; # Wait two hours 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 93  my $executable      = $0; # Get the full Line 94  my $executable      = $0; # Get the full
 #  #
 #  The variables below are only used by the child processes.  #  The variables below are only used by the child processes.
 #  #
 my $RemoteHost; # Name of host child is talking to.  my $RemoteHost; # Hostname of host child is talking to.
 my $RemoteHostId; # default lonid of host child is talking to.  my $RemoteHostId; # lonid of host child is talking to.
   my $RemoteDefHostId; # default lonhostID of host child is talking to.
 my @all_host_ids;  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
Line 349  sub child_exit { Line 351  sub child_exit {
   
 =head2 Tick  =head2 Tick
   
 Invoked  each timer tick.  Invoked each timer tick.
   
 =cut  =cut
   
Line 441  Trigger disconnections of idle sockets. Line 443  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 487  sub ServerToIdle { Line 490  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 558  sub ClientWritable { Line 561  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 587  Parameters: Line 591  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 609  sub CompleteTransaction { Line 613  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 628  sub CompleteTransaction { Line 632  sub CompleteTransaction {
   
 =item data  =item data
   
     The data to send to apached client.      The data to send to apache client.
   
 =cut  =cut
   
Line 739  Parameters: Line 743  Parameters:
     
   The socket to kill off.    The socket to kill off.
   
 =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
   
 sub KillSocket {  sub KillSocket {
     my $Socket = shift;      my $Socket = shift;
       my $restart = shift;
   
     Log("WARNING", "Shutting down a socket");      Log("WARNING", "Shutting down a socket");
     $Socket->Shutdown();      $Socket->Shutdown();
Line 763  sub KillSocket { Line 768  sub KillSocket {
     if(exists($ActiveConnections{$Socket})) {      if(exists($ActiveConnections{$Socket})) {
  $ActiveConnections{$Socket}->cancel;   $ActiveConnections{$Socket}->cancel;
  delete($ActiveConnections{$Socket});   delete($ActiveConnections{$Socket});
  $ConnectionCount--;          # Decrement ConnectionCount unless we will immediately
           # re-connect (i.e., $restart is true), because this was
           # a connection where the SSL channel for exchange of the
           # shared key failed, and we may use an insecure channel.
           unless ($restart) {
       $ConnectionCount--;
           }
  if ($ConnectionCount < 0) { $ConnectionCount = 0; }   if ($ConnectionCount < 0) { $ConnectionCount = 0; }
     }      }
     #  If the connection count has gone to zero and there is work in the      #  If the connection count has gone to zero and there is work in the
     #  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...
           &clear_childpid($$);
     }      }
     UpdateStatus();      UpdateStatus();
 }  }
Line 785  is readable.  The action is state depend Line 799  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 795  The connection must echo the challenge b Line 809  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 821  The the key has been requested, now we a Line 835  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 840  to readable to receive the reply. Line 854  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 868  sub LondReadable { Line 882  sub LondReadable {
   
  Log("WARNING",   Log("WARNING",
     "Lond connection lost.");      "Lond connection lost.");
           my $state_on_exit = $Socket->GetState();
  if(exists($ActiveTransactions{$Socket})) {   if(exists($ActiveTransactions{$Socket})) {
     FailTransaction($ActiveTransactions{$Socket});      FailTransaction($ActiveTransactions{$Socket});
  } else {   } else {
     #  Socket is connecting and failed... need to mark      #  Socket is connecting and failed... need to mark
     #  no longer connecting.      #  no longer connecting.
      
     $LondConnecting = 0;      $LondConnecting = 0;
  }   }
  $Watcher->cancel();   $Watcher->cancel();
  KillSocket($Socket);          if ($state_on_exit eq 'ReInitNoSSL') {
  $ConnectionRetriesLeft--;       # Counts as connection failure              # SSL certificate verification failed, and insecure connection
               # allowed. Send restart arg to KillSocket(), so EmptyQueue() 
               # is not called, as we still hope to process queued request.
   
               KillSocket($Socket,1);
   
               # Re-initiate creation of Lond Connection for use with queued
               # request.
   
               ShowStatus("Connected to ".$RemoteHost);
               Log("WARNING","No SSL channel (verification failed), will try with insecure channel");
               &MakeLondConnection(1);
   
           } else {
       KillSocket($Socket);
       $ConnectionRetriesLeft--;       # Counts as connection failure         
           }
  return;   return;
     }      }
     SocketDump(6,$Socket);      SocketDump(6,$Socket);
Line 889  sub LondReadable { Line 919  sub LondReadable {
     if($State eq "Initialized") {      if($State eq "Initialized") {
   
   
       } elsif ($State eq "ReInitNoSSL") {
   
     } elsif ($State eq "ChallengeReceived") {      } elsif ($State eq "ChallengeReceived") {
  #  The challenge must be echoed back;  The state machine   #  The challenge must be echoed back;  The state machine
  # in the connection takes care of setting that up.  Just   # in the connection takes care of setting that up.  Just
Line 925  sub LondReadable { Line 957  sub LondReadable {
     } elsif ($State eq "ReceivingKey") {      } elsif ($State eq "ReceivingKey") {
   
     } elsif ($State eq "Idle") {      } elsif ($State eq "Idle") {
      
           if ($ConnectionCount == 1) { 
               # Write child Pid file to keep track of ssl and insecure
               # connections
   
               &record_childpid($Socket);
           }
   
  # This is as good a spot as any to get the peer version   # This is as good a spot as any to get the peer version
  # string:   # string:
         
Line 945  sub LondReadable { Line 984  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 982  event.  The action taken is very state d Line 1022  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 1089  sub LondWritable { Line 1129  sub LondWritable {
   
  $Watcher->cb(\&LondReadable);   $Watcher->cb(\&LondReadable);
  $Watcher->poll("r");   $Watcher->poll("r");
   
       } elsif ($State eq "ReInitNoSSL") {
   
     } elsif ($State eq "ChallengeReceived") {      } elsif ($State eq "ChallengeReceived") {
  # We received the challenge, now we    # We received the challenge, now we 
  # are echoing it back. This is a no-op,   # are echoing it back. This is a no-op,
Line 1193  sub QueueDelayed { Line 1235  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.
   
 =cut  =cut
   
 sub MakeLondConnection {       sub MakeLondConnection {
       my ($restart) = @_;
     Debug(4,"MakeLondConnection to ".GetServerHost()." on port "      Debug(4,"MakeLondConnection to ".GetServerHost()." on port "
   .GetServerPort());    .GetServerPort());
   
     my $Connection = LondConnection->new(&GetServerHost(),      my $Connection = LondConnection->new(&GetServerHost(),
  &GetServerPort(),   &GetServerPort(),
  &GetHostId());   &GetHostId(),
    &GetDefHostId());
   
     if($Connection eq undef) {      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.   $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
Line 1238  sub MakeLondConnection { Line 1281  sub MakeLondConnection {
  if ($ConnectionCount == 0) {   if ($ConnectionCount == 0) {
     &SetupTimer; # Need to handle timeouts with connections...      &SetupTimer; # Need to handle timeouts with connections...
  }   }
  $ConnectionCount++;          unless ($restart) {
       $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());
  return 1; # Return success.   return 1; # Return success.
     }      }
Line 1264  reply. Line 1310  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 1350  sub QueueTransaction { Line 1396  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 1454  sub accept_client { Line 1500  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 1505  sub GetServerHost { Line 1551  sub GetServerHost {
   
 =pod  =pod
   
 =head2 GetServerId  =head2 GetHostId
   
 Returns the hostid whose lond we talk with.  Returns the hostid whose lond we talk with.
   
Line 1517  sub GetHostId { Line 1563  sub GetHostId {
   
 =pod  =pod
   
   =head2 GetDefHostId
   
   Returns the default hostid for the node whose lond we talk with.
   
   =cut
   
   sub GetDefHostId {                      # Setup by the fork.
       return $RemoteDefHostId;
   }
   
   =pod
   
 =head2 GetServerPort  =head2 GetServerPort
   
 Returns the lond port number.  Returns the lond port number.
Line 1534  sub GetServerPort { Line 1592  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 1647  sub SignalledToDeath { Line 1705  sub SignalledToDeath {
  ."died through "."\"$signal\"");   ."died through "."\"$signal\"");
     #LogPerm("F:lonc: $$ on $RemoteHost signalled to death: "      #LogPerm("F:lonc: $$ on $RemoteHost signalled to death: "
 #    ."\"$signal\"");  #    ."\"$signal\"");
       &clear_childpid($$);
     exit 0;      exit 0;
   
 }  }
Line 1674  sub ToggleDebug { Line 1733  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 1732  sub ChildProcess { Line 1791  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 1770  sub ChildProcess { Line 1836  sub ChildProcess {
 #  Create a new child for host passed in:  #  Create a new child for host passed in:
   
 sub CreateChild {  sub CreateChild {
     my ($host, $hostid) = @_;      my ($host, $hostid, $defhostid) = @_;
   
     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
Line 1784  sub CreateChild { Line 1851  sub CreateChild {
  undef(@all_host_ids);   undef(@all_host_ids);
     } else { # child.      } else { # child.
  $RemoteHostId = $hostid;   $RemoteHostId = $hostid;
    $RemoteDefHostId = $defhostid;
  ShowStatus("Connected to ".$RemoteHost);   ShowStatus("Connected to ".$RemoteHost);
  $SIG{INT} = 'DEFAULT';   $SIG{INT} = 'DEFAULT';
  sigprocmask(SIG_UNBLOCK, $sigset);   sigprocmask(SIG_UNBLOCK, $sigset);
Line 1851  sub get_remote_hostname { Line 1919  sub get_remote_hostname {
     (my $hostname,my $lonid,@all_host_ids) = split(':',$data);      (my $hostname,my $lonid,@all_host_ids) = split(':',$data);
     $ChildHost{$hostname}++;      $ChildHost{$hostname}++;
     if ($ChildHost{$hostname} == 1) {      if ($ChildHost{$hostname} == 1) {
  &CreateChild($hostname,$lonid);   &CreateChild($hostname,$lonid,$all_host_ids[-1]);
     } else {      } else {
  &Log('WARNING',"Request for a second child on $hostname");   &Log('WARNING',"Request for a second child on $hostname");
     }      }
Line 1959  sub server_died { Line 2027  sub server_died {
  my $host = $ChildPid{$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");
               &clear_childpid($pid);
     delete($ChildPid{$pid});      delete($ChildPid{$pid});
     delete($ChildHost{$host});      delete($ChildHost{$host});
     &parent_clean_up($host);      &parent_clean_up($host);
Line 2067  die "Main Event loop exited: $ret"; Line 2136  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 2129  sub UpdateKids { Line 2198  sub UpdateKids {
     # (lost unless they are critical).      # (lost unless they are critical).
   
     &KillThemAll();      &KillThemAll();
       LondConnection->ResetReadConfig();
       ShowStatus('Parent keeping the flock');
 }  }
   
   
Line 2137  sub UpdateKids { Line 2208  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 2172  sub KillThemAll { Line 2244  sub KillThemAll {
  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;
           &clear_childpid($pid);
     }      }
     ShowStatus("Finished killing child processes off.");      ShowStatus("Finished killing child processes off.");
 }  }
Line 2191  sub really_kill_them_all_dammit Line 2264  sub really_kill_them_all_dammit
  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($ChildPid{$pid});   delete($ChildPid{$pid});
           delete($ChildKeyMode{$pid});
  my $execdir = $perlvar{'lonDaemons'};   my $execdir = $perlvar{'lonDaemons'};
  unlink("$execdir/logs/lonc.pid");   unlink("$execdir/logs/lonc.pid");
     }      }
Line 2219  sub Terminate { Line 2293  sub Terminate {
   
 }  }
   
   =pod
   
   =cut
   
 sub my_hostname {  sub my_hostname {
     use Sys::Hostname;      use Sys::Hostname::FQDN();
     my $name = &hostname();      my $name = Sys::Hostname::FQDN::fqdn();
     &Debug(9,"Name is $name");      &Debug(9,"Name is $name");
     return $name;      return $name;
 }  }
   
   sub record_childpid {
       my ($Socket) = @_;
       my $docdir = $perlvar{'lonDocRoot'};
       my $authmode = $Socket->GetKeyMode();
       my $peer = $Socket->PeerLoncapaHim();
       if (($authmode eq 'ssl') || ($authmode eq 'insecure')) {
           my $childpid = $$;
           if ($childpid) {
               unless (exists($ChildKeyMode{$childpid})) {
                   $ChildKeyMode{$childpid} = $authmode;
               }
               if (-d "$docdir/lon-status/loncchld") {
                   unless (-e "$docdir/lon-status/loncchld/$childpid") {
                       if (open (my $pidfh,'>',"$docdir/lon-status/loncchld/$childpid")) {
                           print $pidfh "$peer:$authmode\n";
                           close($pidfh);
                       }
                   }
               }
           }
       }
       return;
   }
   
   sub clear_childpid {
       my ($childpid) = @_; 
       my $docdir = $perlvar{'lonDocRoot'};
       if (-d "$docdir/lon-status/loncchld") {
           if ($childpid =~ /^\d+$/) {
               if (($ChildKeyMode{$childpid} eq 'insecure') ||
                   ($ChildKeyMode{$childpid} eq 'ssl')) {
                   if (-e "$docdir/lon-status/loncchld/$childpid") {
                       unlink("$docdir/lon-status/loncchld/$childpid");
                   }
               }
           }
       }
       if (exists($ChildKeyMode{$childpid})) {
           delete($ChildKeyMode{$childpid});
       }
       return;
   }
   
 =pod  =pod
   
 =head1 Theory  =head1 Theory
Line 2283  If there are pending transactions in the Line 2404  If there are pending transactions in the
 they are failed (saved if critical).  If the connection  they are failed (saved if critical).  If the connection
 retry count gets exceeded by this, the  retry count gets exceeded by this, the
 remote host is marked as dead.  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.  connection dialog with a remote host.
   
 =item Critical Host makred DEAD <hostname>     =item Critical Host makred DEAD <hostname>   
Line 2330  connection or died.  This should be foll Line 2451  connection or died.  This should be foll
   
  "WARNING Failing transaction..." msgs for each in-flight or queued transaction.   "WARNING Failing transaction..." msgs for each in-flight or queued transaction.
   
   =item WARNING No SSL channel (verification failed), will try with insecure channel.
   
   Called when promotion of a socket to SSL failed because SSL certificate verification failed.
   Domain configuration must also permit insecure channel use for key exchange. Connection
   negotiation will start again from the beginning, but with Authentication Mode not set to ssl.
   
 =item INFO Connected to lond version:  <version>   =item INFO Connected to lond version:  <version> 
   
 When connection negotiation is complete, the lond version is requested and logged here.  When connection negotiation is complete, the lond version is requested and logged here.
Line 2410  the event processing loop is entered. Line 2537  the event processing loop is entered.
 =item INFO Updating connections via SIGUSR2  =item INFO Updating connections via SIGUSR2
                                                                           
 SIGUSR2 received. The original code would kill all clients, re-read the host file,  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.  just kills all child processes and lets requests start them as needed again.
   
   
Line 2421  SigHUP received.  all the children are k Line 2548  SigHUP received.  all the children are k
 =item CRITICAL Nicely killing lonc for host pid = <pid>  =item CRITICAL Nicely killing lonc for host pid = <pid>
   
 Attempting to kill the child that is serving the specified host (pid given) cleanly via  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 = <pid>  =item CRITICAL Nastily killing lonc for host pid = <pid>
   

Removed from v.1.90  
changed lines
  Added in v.1.107


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>