--- loncom/loncnew	2004/06/01 10:02:13	1.47
+++ loncom/loncnew	2004/09/20 18:40:06	1.55
@@ -2,7 +2,7 @@
 # The LearningOnline Network with CAPA
 # lonc maintains the connections to remote computers
 #
-# $Id: loncnew,v 1.47 2004/06/01 10:02:13 foxr Exp $
+# $Id: loncnew,v 1.55 2004/09/20 18:40:06 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -82,7 +82,7 @@ my $ClientConnection = 0;	# Uniquifier f
 
 my $DebugLevel = 0;
 my $NextDebugLevel= 2;		# So Sigint can toggle this.
-my $IdleTimeout= 3600;		# Wait an hour before pruning connections.
+my $IdleTimeout= 600;		# Wait 10 minutes before pruning connections.
 
 my $LogTransactions = 0;	# When True, all transactions/replies get logged.
 
@@ -103,6 +103,8 @@ my $RecentLogEntry  = "";
 my $ConnectionRetries=2;	# Number of connection retries allowed.
 my $ConnectionRetriesLeft=2;	# Number of connection retries remaining.
 my $LondVersion     = "unknown"; # Version of lond we talk with.
+my $KeyMode         = "";       # e.g. ssl, local, insecure from last connect.
+my $LondConnecting  = 0;       # True when a connection is being built.
 
 #
 #   The hash below gives the HTML format for log messages
@@ -232,7 +234,7 @@ sub SocketDump {
     my ($level, $socket) = @_;
 
     if($level <= $DebugLevel) {
-	$socket->Dump();
+	$socket->Dump(-1);	# Ensure it will get dumped.
     }
 }
 
@@ -264,8 +266,8 @@ sub ShowStatus {
 sub SocketTimeout {
     my $Socket = shift;
     Log("WARNING", "A socket timeout was detected");
-    Debug(0, " SocketTimeout called: ");
-    $Socket->Dump();
+    Debug(5, " SocketTimeout called: ");
+    $Socket->Dump(0);
     if(exists($ActiveTransactions{$Socket})) {
 	FailTransaction($ActiveTransactions{$Socket});
     }
@@ -273,7 +275,7 @@ sub SocketTimeout {
                                 # a connection failure:
     $ConnectionRetriesLeft--;
     if($ConnectionRetriesLeft <= 0) {
-	Log("CRITICAL", "Host marked dead: ".GetServerHost());
+	Log("CRITICAL", "Host marked DEAD: ".GetServerHost());
     }
 
 }
@@ -289,10 +291,14 @@ Invoked  each timer tick.
 
 
 sub Tick {
+    my ($Event)       = @_;
+    my $clock_watcher = $Event->w;
+
     my $client;
     if($ConnectionRetriesLeft > 0) {
 	ShowStatus(GetServerHost()." Connection count: ".$ConnectionCount
-		   ." Retries remaining: ".$ConnectionRetriesLeft);
+		   ." Retries remaining: ".$ConnectionRetriesLeft
+		   ." ($KeyMode)");
     } else {
 	ShowStatus(GetServerHost()." >> DEAD <<");
     }
@@ -305,6 +311,7 @@ sub Tick {
 	if($IdleSeconds > $IdleTimeout) { # Prune a connection...
 	    my $Socket = $IdleConnections->pop();
 	    KillSocket($Socket);
+	    $IdleSeconds = 0;	# Otherwise all connections get trimmed to fast.
 	}
     } else {
 	$IdleSeconds = 0;	# Reset idle count if not idle.
@@ -347,6 +354,10 @@ sub Tick {
 	}
        
     }
+    if ($ConnectionCount == 0) {
+	$KeyMode = ""; 
+	$clock_watcher->cancel();
+    }
 }
 
 =pod
@@ -387,6 +398,7 @@ long enough, it will be shut down and re
 
 sub ServerToIdle {
     my $Socket   = shift;	# Get the socket.
+    $KeyMode = $Socket->{AuthenticationMode};
     delete($ActiveTransactions{$Socket}); # Server has no transaction
 
     &Debug(5, "Server to idle");
@@ -466,7 +478,7 @@ sub ClientWritable {
 	    } else {		# Partial string sent.
 		$Watcher->data(substr($Data, $result));
 		if($result == 0) {    # client hung up on us!!
-		    Log("INFO", "lonc pipe client hung up on us!");
+		    # Log("INFO", "lonc pipe client hung up on us!");
 		    $Watcher->cancel;
 		    $Socket->shutdown(2);
 		    $Socket->close();
@@ -594,7 +606,13 @@ Parameters:
 
 sub FailTransaction {
     my $transaction = shift;
-    Log("WARNING", "Failing transaction ".$transaction->getRequest());
+    
+    #  If the socket is dead, that's already logged.
+
+    if ($ConnectionRetriesLeft > 0) {
+	Log("WARNING", "Failing transaction "
+	    .$transaction->getRequest());
+    }
     Debug(1, "Failing transaction: ".$transaction->getRequest());
     if (!$transaction->isDeferred()) { # If the transaction is deferred we'll get to it.
 	my $client  = $transaction->getClient();
@@ -855,6 +873,10 @@ sub LondReadable {
 		.$RemoteHost." now ready for action");
 	}
 	ServerToIdle($Socket);	# Next work unit or idle.
+
+	#
+	$LondConnecting = 0;	# Best spot I can think of for this.
+	# 
 	
     } elsif ($State eq "SendingRequest") {
 	#  We need to be writable for this and probably don't belong
@@ -1128,7 +1150,9 @@ sub MakeLondConnection {
 			   data     => $Connection,
 			   desc => 'Connection to lond server');
 	$ActiveConnections{$Connection} = $event;
-	
+	if ($ConnectionCount == 0) {
+	    &SetupTimer;	# Need to handle timeouts with connections...
+	}
 	$ConnectionCount++;
 	Debug(4, "Connection count = ".$ConnectionCount);
 	if($ConnectionCount == 1) { # First Connection:
@@ -1136,6 +1160,7 @@ sub MakeLondConnection {
 	}
 	Log("SUCESS", "Created connection ".$ConnectionCount
 	    ." to host ".GetServerHost());
+	$LondConnecting = 1;	# Connection in progress.
 	return 1;		# Return success.
     }
     
@@ -1219,7 +1244,7 @@ sub QueueTransaction {
     if(!defined $LondSocket) {	# Need to queue request.
 	Debug(5,"Must queue...");
 	$WorkQueue->enqueue($requestData);
-	if($ConnectionCount < $MaxConnectionCount) {
+	if(($ConnectionCount < $MaxConnectionCount) && !$LondConnecting) {
 	    if($ConnectionRetriesLeft > 0) {
 		Debug(5,"Starting additional lond connection");
 		if(MakeLondConnection() == 0) {
@@ -1381,7 +1406,7 @@ sub SetupLoncListener {
     my $SocketName = GetLoncSocketPath();
     unlink($SocketName);
     unless ($socket =IO::Socket::UNIX->new(Local  => $SocketName,
-					    Listen => 10, 
+					    Listen => 250, 
 					    Type   => SOCK_STREAM)) {
 	die "Failed to create a lonc listner socket";
     }
@@ -1441,7 +1466,7 @@ sub ChildStatus {
 	    my $state  = $Socket->GetState();
 	    print $fh "Connection $i State: $state\n";
 	    print STDERR "---------------------- Connection $i \n";
-	    $Socket->Dump();
+	    $Socket->Dump(-1);	# Ensure it gets dumped..
 	    $i++;	
 	}
     }
@@ -1515,7 +1540,6 @@ sub ChildProcess {
 		  cb       => \&ToggleDebug,
 		  data     => "INT");
 
-    SetupTimer();
     
     SetupLoncListener();
     
@@ -1538,9 +1562,10 @@ sub ChildProcess {
 #  Create a new child for host passed in:
 
 sub CreateChild {
+    my $host = shift;
+
     my $sigset = POSIX::SigSet->new(SIGINT);
     sigprocmask(SIG_BLOCK, $sigset);
-    my $host = shift;
     $RemoteHost = $host;
     Log("CRITICAL", "Forking server for ".$host);
     my $pid          = fork;
@@ -1811,17 +1836,33 @@ sub KillThemAll {
     local($SIG{CHLD}) = 'IGNORE';      # Our children >will< die.
     foreach my $pid (keys %ChildHash) {
 	my $serving = $ChildHash{$pid};
-	Debug(2, "Killing lonc for $serving pid = $pid");
-	ShowStatus("Killing lonc for $serving pid = $pid");
-	Log("CRITICAL", "Killing lonc for $serving pid = $pid");
+	ShowStatus("Nicely Killing lonc for $serving pid = $pid");
+	Log("CRITICAL", "Nicely Killing lonc for $serving pid = $pid");
 	kill 'QUIT' => $pid;
-	delete($ChildHash{$pid});
     }
-    my $execdir = $perlvar{'lonDaemons'};
-    unlink("$execdir/logs/lonc.pid");
+
 
 }
 
+
+#
+#  Kill all children via KILL.  Just in case the
+#  first shot didn't get them.
+
+sub really_kill_them_all_dammit
+{
+    Debug(2, "Kill them all Dammit");
+    local($SIG{CHLD} = 'IGNORE'); # In case some purist reenabled them.
+    foreach my $pid (keys %ChildHash) {
+	my $serving = $ChildHash{$pid};
+	&ShowStatus("Nastily killing lonc for $serving pid = $pid");
+	Log("CRITICAL", "Nastily killing lonc for $serving pid = $pid");
+	kill 'KILL' => $pid;
+	delete($ChildHash{$pid});
+	my $execdir = $perlvar{'lonDaemons'};
+	unlink("$execdir/logs/lonc.pid");
+    }
+}
 =pod
 
 =head1 Terminate
@@ -1831,7 +1872,15 @@ Terminate the system.
 =cut
 
 sub Terminate {
-    KillThemAll;
+    &Log("CRITICAL", "Asked to kill children.. first be nice...");
+    &KillThemAll;
+    #
+    #  By now they really should all be dead.. but just in case 
+    #  send them all SIGKILL's after a bit of waiting:
+
+    sleep(4);
+    &Log("CRITICAL", "Now kill children nasty");
+    &really_kill_them_all_dammit;
     Log("CRITICAL","Master process exiting");
     exit 0;