3
votes

I have an Indy Server TIdTCPServer which has 3 bindings for different ports. If I connect a client to those 3 ports, and then deactivate the server, it gets stuck in what appears to be a deadlock. No matter what I do, it won't respond to my click, it won't even report "not responding" to Windows. If I disconnect the client(s) before deactivating the server, everything goes just perfect. I mean "deactivating" as in Server.Active:= False;.

Has anyone else experienced this? What might be causing it? I have nothing happening in here which crosses over threads which could in turn cause a deadlock (for example GUI updates). I tried an Antifreeze component TIdAntiFreeze but no luck.

2
What happens if you have no connections does it deactivate correctly? if so try terminating the connections from the clients before deactivating the server - Shaun07776
Yes, it deactivates successfully if there are no more client connections. - Jerry Dodge
TIdTCPServer's Active property setter automatically disconnects any active client connections. But it also has to wait for those threads to terminate, and that is where this kind of deadlocking occurs, if those threads are not terminating correctly, typically due to user error in the event handler code. We need to see Jerry's actual code. - Remy Lebeau
Thanks @Remy, as I'm reading your comments in Indy's TIdCustomTCPServer.TerminateAllThreads... Unless "RLebeau" is someone else? :P Proof that you DO know what you're talking about - Jerry Dodge
Yes, that is me. I am on the Indy development team. - Remy Lebeau

2 Answers

4
votes

TIdTCPServer is a multi-threaded component. A deadlock during server deactivation means that one or more of its client threads is not terminating correctly. That usually means that your server event handlers are doing something they should not be doing, typically either catching and discarding Indy's internal exceptions to itself, synchronizing with the thread context that is busy terminating the server, or deadlocking on something else outside of Indy. Without seeing your actual code, there is no way to know for sure which is actually the case, but it is always user error that causes this kind of deadlock.

TIdAntiFreeze only affects Indy components that run in the context of the main thread. TIdTCPServer does not.

1
votes

I added this code on Form.OnClose works good!

procedure TformSFTP.FormClose(Sender: TObject; var Action: TCloseAction);
var
  iA : Integer;
  Context: TidContext;
begin
 if sftpServidorFTP.Active then
     with sftpServidorFTP.Contexts.LockList do
        try
           for iA := Count - 1 downto 0 do
           begin
              Context := Items[iA];
              if Context = nil then
                 Continue;
              Context.Connection.IOHandler.WriteBufferClear;
              Context.Connection.IOHandler.InputBuffer.Clear;
              Context.Connection.IOHandler.Close;
              if Context.Connection.Connected then
                 Context.Connection.Disconnect;
           end;
        finally
           sftpServidorFTP.Contexts.UnlockList;
        end;

if sftpServidorFTP.Active then

sftpServidorFTP.Active := False;

end;