With open connections IdTCPServer.Active:=false; causes the program to hang. How to kill all active connections and stop IdTCPServer? I am trying to do the following:
procedure TMyServer.Stop;
var
List: TList;
i: Integer;
begin
List := Contexts.LockList;
try
for i := List.Count - 1 downto 0 do begin
TMyContext(List.Items[i]).WaitDisconnect := True;
end;
finally
Contexts.UnlockList;
end;
// Active := False;
Timer.OnTimer := ProcTimer;
Timer.Enabled := True;
end;
TMyContext = class(TIdServerContext)
public
WaitDisconnect: Boolean;
end;
procedure TMyServer.Execute(AContext: TIdContext);
var
Ctx: TMyContext;
begin
Ctx := TMyContext(AContext);
if not Ctx.WaitDisconnect then begin
//read data
else begin
TMyContext(AContext).Connection.Disconnect;
end;
end;
procedure TMyServer.ProcTimer(Sender: TObject);
var
ClientsCount: Integer;
begin
with Contexts.LockList do
try
ClientsCount := Count;
finally
Contexts.UnlockList;
end;
if ClientsCount = 0 then begin
Active := False;
Timer.Enabled := False;
end;
end;
With open connections IdTCPServer.Active:=false; causes the program to hang.
The only way that can happen is if you are deadlocking the server.
That can happen if you deactivate the server from the context of your main UI thread while your server's event handlers are synchronously syncing with the main UI thread at the same time (TIdSync
, TThread.Synchronize()
, SendMessage()
, etc).
It could also happen if your client threads are doing something that is not thread-safe, like accessing the UI without proper synchronization.
Deactivating the server closes all active sockets and waits for their threads to terminate. But if one or more client threads are blocked waiting on the main UI thread, or are otherwise deadlocked on something else, and the main UI thread is blocked waiting for the server to deactivate, then that is a deadlock that hangs the program.
To work around that, you need to make sure your server code is thread-safe, and that you either:
use asynchronous syncs (TIdNotify
, TThread.Queue()
, PostMessage()
, etc) so the client threads are not blocked waiting on the main UI thread.
deactivate the server from a worker thread so the main UI thread is free to process sync requests normally.