11

How should I be recovering in this situation?

The server crashes, thus the connection has been abnormally closed. Calls to almost everything result in "Connection Reset By Peer" exceptions. I seem to have fixed it by calling Disconnect on the TIdTCPClient object inside the except block, but it results in one final exception with the same message (which I have caught in the second try-except block).

This is with Indy10 and Delphi XE2.

   try
      if not EcomSocket.Connected then EcomSocket.Connect();
    except
      on e: Exception do begin
        try
          EcomSocket.Disconnect();
        except
          MessageDlg('Connectivity to the server has been lost.', mtError, [mbOK], 0);
        end;
      end;
    end;
Andy Clark
  • 516
  • 1
  • 4
  • 21
  • Did you try to debug into TIdTCPConnection.Disconnect in IdTCPConnection.pas? Maybe a OnDisconnect handler is executed and uses the connection. Or the NotifyPeer plays a role, see also the comments in the source about different scenarios – mjn May 09 '12 at 13:45
  • Freeing the object and creating a fresh new one will help (but not help to find the reason for the exception) – mjn May 09 '12 at 13:46
  • I am not so much concerned with why I am getting an exception when calling disconnect. I just want to know how to properly recover from a situation like this. – Andy Clark May 09 '12 at 14:14
  • This is hard to say without knowing what the program does – mjn May 09 '12 at 14:57
  • This is what I consider to be relevant (so feel free to ask for more). The client is our GUI, which issues commands to a server within our system. The client should recognize when the connection has failed and attempt to reconnect until the connection has been re-established. I have it working exactly as I want now. When the server terminates correctly, it calls DisconnectNotifyPeers, and the connections are closed cleanly. When the server terminates abnormally, the clients will recognize this and act appropriately. It is the code that is the problem. I'll post it below. – Andy Clark May 09 '12 at 15:10
  • I can't figure out how to format code in these comments, so I've put it on [pastie](http://pastie.org/3884729) – Andy Clark May 09 '12 at 15:11
  • That code is in a timer. When a server terminates abnormally, checking Connected will throw an exception. Then the Disconnect method will throw another exception, despite doing what it needed to do. Then it will quietly wait for the server to come back up. – Andy Clark May 09 '12 at 15:20
  • `Connected()` performs a read operation to determine the socket status, so that could raise an exception if a socket error is reported. `Disconnect()` performs a write operation if you are using a `TIdTCPClient` descendant that overrides the virtual `DisconnectNotifyPeer()` method, so that could raise an exception as well. When calling `Disconnect()` after an error, you should set the `ANotifyPeer` parameter to False, and you should also clear the `IOHandler.InputBuffer` to remove any unread data otherwise `Connected()` can return True and make `Connect()` raise another exception. – Remy Lebeau May 09 '12 at 20:11

1 Answers1

11

Try this:

try 
  if not EcomSocket.Connected then EcomSocket.Connect(); 
except 
  try 
    EcomSocket.Disconnect(False); 
  except 
  end; 
  if EcomSocket.IOHandler <> nil then EcomSocket.IOHandler.InputBuffer.Clear; 
  MessageDlg('Connectivity to the server has been lost.', mtError, [mbOK], 0); 
end; 
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • 2
    Passing "false" to the Disconnect method fixed it. Its default behavior is to call DisconnectNotifyPeer, which triggered the second exception. – Andy Clark May 10 '12 at 14:44