--- loncom/loncnew 2004/02/09 13:39:28 1.41 +++ loncom/loncnew 2004/02/17 09:43:21 1.42 @@ -2,7 +2,7 @@ # The LearningOnline Network with CAPA # lonc maintains the connections to remote computers # -# $Id: loncnew,v 1.41 2004/02/09 13:39:28 albertel Exp $ +# $Id: loncnew,v 1.42 2004/02/17 09:43:21 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -262,9 +262,16 @@ sub SocketTimeout { Log("WARNING", "A socket timeout was detected"); Debug(0, " SocketTimeout called: "); $Socket->Dump(); + if(exists($ActiveTransactions{$Socket})) { + FailTransaction($ActiveTransactions{$Socket}); + } KillSocket($Socket); # A transaction timeout also counts as # a connection failure: $ConnectionRetriesLeft--; + if($ConnectionRetriesLeft <= 0) { + Log("CRITICAL", "Host marked dead: ".GetServerHost()); + } + } #----------------------------- Timer management ------------------------ @@ -326,11 +333,13 @@ sub Tick { if($successCount == 0) { # All connections failed: Debug(5,"Work in queue failed to make any connectiouns\n"); EmptyQueue(); # Fail pending transactions with con_lost. + CloseAllLondConnections(); # Should all be closed but.... } } else { ShowStatus(GetServerHost()." >>> DEAD!!! <<<"); Debug(5,"Work in queue, but gave up on connections..flushing\n"); EmptyQueue(); # Connections can't be established. + CloseAllLondConnections(); # Should all already be closed but... } } @@ -521,7 +530,9 @@ sub CompleteTransaction { unlink $Transaction->getFile(); } } + =pod + =head1 StartClientReply Initiates a reply to a client where the reply data is a parameter. @@ -537,6 +548,7 @@ sub CompleteTransaction { The data to send to apached client. =cut + sub StartClientReply { my $Transaction = shift; my $data = shift; @@ -554,7 +566,9 @@ sub StartClientReply { cb => \&ClientWritable, data => $data); } + =pod + =head2 FailTransaction Finishes a transaction with failure because the associated lond socket @@ -564,8 +578,7 @@ sub StartClientReply { - The transaction is 'live' in which case we initiate the sending of "con_lost" to the client. -Deleting the transaction means killing it from the -%ActiveTransactions hash. +Deleting the transaction means killing it from the %ActiveTransactions hash. Parameters: @@ -573,6 +586,7 @@ Parameters: The LondTransaction we are failing. + =cut sub FailTransaction { @@ -584,9 +598,6 @@ sub FailTransaction { Debug(1," Replying con_lost to ".$transaction->getRequest()); StartClientReply($transaction, "con_lost\n"); } - if($ConnectionRetriesLeft <= 0) { - Log("CRITICAL", "Host marked dead: ".GetServerHost()); - } } @@ -614,7 +625,10 @@ Close all connections open on lond prior =cut sub CloseAllLondConnections { foreach my $Socket (keys %ActiveConnections) { - KillSocket($Socket); + if(exists($ActiveTransactions{$Socket})) { + FailTransaction($ActiveTransactions{$Socket}); + } + KillSocket($Socket); } } =cut @@ -666,6 +680,7 @@ sub KillSocket { # if($ConnectionCount == 0) { EmptyQueue(); + CloseAllLondConnections; # Should all already be closed but... } } @@ -932,21 +947,36 @@ sub LondWritable { SocketDump(6,$Socket); + # If the socket is writable, we must always write. + # Only by writing will we undergo state transitions. + # Old logic wrote in state specific code below, however + # That forces us at least through another invocation of + # this function after writability is possible again. + # This logic also factors out common code for handling + # write failures... in all cases, write failures + # Kill the socket. + # This logic makes the branches of the >big< if below + # so that the writing states are actually NO-OPs. + + if ($Socket->Writable() != 0) { + # The write resulted in an error. + # We'll treat this as if the socket got disconnected: + Log("WARNING", "Connection to ".$RemoteHost. + " has been disconnected"); + if(exists($ActiveTransactions{$Socket})) { + FailTransaction($ActiveTransactions{$Socket}); + } + $Watcher->cancel(); + KillSocket($Socket); + return; + } + + + if ($State eq "Connected") { - if ($Socket->Writable() != 0) { - # The write resulted in an error. - # We'll treat this as if the socket got disconnected: - Log("WARNING", "Connection to ".$RemoteHost. - " has been disconnected"); - FailTransaction($ActiveTransactions{$Socket}); - $Watcher->cancel(); - KillSocket($Socket); - return; - } - # "init" is being sent... - + } elsif ($State eq "Initialized") { # Now that init was sent, we switch @@ -960,13 +990,6 @@ sub LondWritable { # are echoing it back. This is a no-op, # we're waiting for the state to change - if($Socket->Writable() != 0) { - - $Watcher->cancel(); - KillSocket($Socket); - return; - } - } elsif ($State eq "ChallengeReplied") { # The echo was sent back, so we switch # to watching readability. @@ -975,12 +998,7 @@ sub LondWritable { $Watcher->poll("r"); } elsif ($State eq "RequestingVersion") { # Sending the peer a version request... - - if($Socket->Writable() != 0) { - $Watcher->cancel(); - KillSocket($Socket); - return; - } + } elsif ($State eq "ReadingVersionString") { # Transition to read since we have sent the # version command and now just need to read the @@ -991,12 +1009,7 @@ sub LondWritable { } elsif ($State eq "SetHost") { # Setting the remote domain... - - if($Socket->Writable() != 0) { - $Watcher->cancel(); - KillSocket($Socket); - return; - } + } elsif ($State eq "HostSet") { # Back to readable to get the ok. @@ -1007,17 +1020,7 @@ sub LondWritable { } elsif ($State eq "RequestingKey") { # At this time we're requesting the key. # again, this is essentially a no-op. - # we'll write the next chunk until the - # state changes. - - if($Socket->Writable() != 0) { - # Write resulted in an error. - $Watcher->cancel(); - KillSocket($Socket); - return; - - } } elsif ($State eq "ReceivingKey") { # Now we need to wait for the key # to come back from the peer: @@ -1030,17 +1033,6 @@ sub LondWritable { # At this time we are sending a request to the # peer... write the next chunk: - if($Socket->Writable() != 0) { - - if(exists($ActiveTransactions{$Socket})) { - Debug(3, "Lond connection lost, failing transactions"); - FailTransaction($ActiveTransactions{$Socket}); - } - $Watcher->cancel(); - KillSocket($Socket); - return; - - } } elsif ($State eq "ReceivingReply") { # The send has completed. Wait for the @@ -1229,10 +1221,12 @@ sub QueueTransaction { Debug(5,"Starting additional lond connection"); if(MakeLondConnection() == 0) { EmptyQueue(); # Fail transactions, can't make connection. + CloseAllLondConnections; # Should all be closed but... } } else { ShowStatus(GetServerHost()." >>> DEAD !!!! <<<"); EmptyQueue(); # It's worse than that ... he's dead Jim. + CloseAllLondConnections; # Should all be closed but.. } } } else { # Can start the request: