08-09-2018, 09:53 PM
(08-06-2018, 09:18 PM)rlebeau Wrote: 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.
So I extended my error logging deeper and CloseSocket(ASocket) is where it hangs when TCPServer is trying to close down the first listening thread. I've modified WSCloseSocket() as such:
Code:
function TIdStackWindows.WSCloseSocket(ASocket: TIdStackSocketHandle): Integer;
begin
LogData.AddError('TIdStackWindows.WSCloseSocket(' + IntToStr(ASocket) + ') Start', True);
try
Result := CloseSocket(ASocket);
except
on E: Exception do
begin
LogData.AddError('WSCloseSocket Exception: ' + E.Message);
raise;
end;
end;
LogData.AddError('TIdStackWindows.WSCloseSocket(' + IntToStr(ASocket) + ') Stop', True);
end;And when it does crash, my log only records that start entry like this:
TIdStackWindows.WSCloseSocket(10384) Start
No exception fires and it never reaches my "Stop" log. I don't know what to do now. You mentioned "non-zero linger timeout". I don't know what that is and so pretty sure I didn't do that. And it's definitely not a stack size issue as I've returned it to the default 1MB setting.

