(08-05-2018, 07:50 PM)kbriggs Wrote: After years of no issues, I'm suddenly having a problem with shutting down a TIdTCPServer component. Setting Active := False is occasionally locking up my app.
Then you are probably using it wrong, like synching worker threads when you should not be. For instance, syncing synchronously with the main UI thread while it is blocked trying to shutdown the server. To avoid that, use asynchronous syncs, or shutdown the server in a separate thread rather than in the UI thread.
(08-05-2018, 07:50 PM)kbriggs Wrote: So much so that the process cannot be killed in either the Windows Task Manager or Process Explorer.
Processes can ALWAYS be killed via the Task Manager, especially from the Processes tab rather than then Applications tab.
(08-05-2018, 07:50 PM)kbriggs Wrote: I upgraded to a more recent Indy version (10.6.2.5469) but the problem persists. It happens maybe 10% of the time even when I perform the same steps over and over.
Hard to diagnose without seeing your actual code (or a demo that reproduces the same issue).
(08-05-2018, 07:50 PM)kbriggs Wrote: By inserting markers in the code to record to an error log (which runs in a critical section) I've traced the problem this deep, where 2 listening threads are supposed to terminate:
Active := False
SetActive
Shutdown
StopListing
LListener.Binding.CloseSocket (if crashes, always does so on the first of two loops)
Disconnect
GStack.Disconnect(Handle)
That last one never returns. It's a virtual abstract method so I'm not sure where to go from there.
On Windows, it is overridden by the TIdStackWindows.Disconnect() method, which simply calls the Winsock API shutdown() and closesocket() functions:
Code:
function TIdStackWindows.WSShutdown(ASocket: TIdStackSocketHandle; AHow: Integer): Integer;
begin
Result := Shutdown(ASocket, AHow); // <-- Winsock API call
end;
function TIdStackWindows.WSCloseSocket(ASocket: TIdStackSocketHandle): Integer;
begin
Result := CloseSocket(ASocket); // <-- Winsock API call
end;
procedure TIdStackWindows.Disconnect(ASocket: TIdStackSocketHandle);
begin
// Windows uses Id_SD_Send, Linux should use Id_SD_Both
WSShutdown(ASocket, Id_SD_Send);
// SO_LINGER is false - socket may take a little while to actually close after this
WSCloseSocket(ASocket);
end;Neither of those API functions should be hanging by default, though closesocket() CAN hang if you have configured the socket beforehand with a non-zero linger timeout (which Indy doesn't do, but users can do manually) and pending data is not being sent to the peer correctly.
(08-05-2018, 07:50 PM)kbriggs Wrote: My app is a game server with an HTTPServer (that servers an HTML5 web app client) and a TCPServer and acts as websocket connection for the client. Both are started and stopped together from a button click in the app's main thread. The HTTPServer never crashes on shutdown, only the TCPServer does.
TIdHTTPServer is a TIdTCPServer descendant. So that begs the question - what is your WebSocket server doing differently that your HTTP server is not doing?
Also, why not use your TIdHTTPServer for your WebSocket server (since WebSocket starts life as HTTP)?
(08-05-2018, 07:50 PM)kbriggs Wrote: I've tried using a worker thread to shut down the TCPServer. That allows me to exit the app when the problem occurs but the EXE is still running on the Processes tab and cannot be killed. I'm using the OnConnect, OnDisconnect, and OnExecute events and all are contained in try/except blocks that reraise Indy exceptions
That means nothing if threads are deadlocking themselves and not cleaning up correctly.
Also, you should remove the try/except blocks and use the TIdTCPServer.OnException event instead for your logging.

