Recent

Author Topic: Indy 10 TCPServer listener error: Error on call to Winsock2 library function WSA  (Read 333 times)

snorkel

  • Hero Member
  • *****
  • Posts: 810
Hi,
Using the build of indy in the package manager and I noticed that when I call myIdtcpServer.active:=false it has been raising this error in the Listener error event:
Server listener exception: Error on call to Winsock2 library function WSAGetLastError: Either the application has not called WSAStartup, or WSAStartup failed.

Using latest Lazarus IDE on windows 10.

Anyone else see this and maybe have a solution?
***Snorkel***
If I forget, I always use the latest stable 32bit version of Lazarus and FPC. At the time of this signature that is Laz 2.06 and FPC 3.0.4
OS: Windows 10 64 bit

Remy Lebeau

  • Hero Member
  • *****
  • Posts: 693
    • Lebeau Software
Using the build of indy in the package manager and I noticed that when I call myIdtcpServer.active:=false it has been raising this error in the Listener error event:
Server listener exception: Error on call to Winsock2 library function WSAGetLastError: Either the application has not called WSAStartup, or WSAStartup failed.

You are going to have to provide a reproducible example.  Simply (de)activating the server does not call WSAStartup()/WSACleanup().  The ONLY way that EXACT error message can occur is when Indy's IdWinsock2.Stub_WSAGetLastError() function is called at runtime and the Winsock DLL is not currently loaded in memory by Indy (the IdWinsock2.WinsockHandle() function returns 0 and the IdWinsock2.Winsock2Loaded() function returns False).

Code: [Select]
function FixupStub(hDll: TIdLibHandle; const AName:{$IFDEF WINCE}TIdUnicodeString{$ELSE}string{$ENDIF}): Pointer;
{$IFDEF USE_INLINE}inline;{$ENDIF}
begin
  if hDll = IdNilHandle then begin
    raise EIdWinsockStubError.Build(WSANOTINITIALISED, RSWinsockCallError, [AName]); // <-- ERROR RAISED HERE!!!
  end;
  Result := Windows.GetProcAddress(hDll, {$IFDEF WINCE}PWideChar{$ELSE}PChar{$ENDIF}(AName));
  if Result = nil then begin
    raise EIdWinsockStubError.Build(WSAEINVAL, RSWinsockCallError, [AName]);
  end;
end;

function Stub_WSAGetLastError: Integer; stdcall;
begin
  @WSAGetLastError := FixupStub(hWinSockDll, 'WSAGetLastError'); {Do not Localize} // <-- ONLY IF hWinSockDll IS 0!!!
  Result := WSAGetLastError;
end;

That can only happen if the following conditions are met:

  • after the IdWinsock2.InitializeStubs() function has been called, which occurs ONLY during initialization of the IdWinsock2.pas unit.
  • IdWinsock2.WSAGetLastError() has not been called before, either by Indy or by user code. Prior to its 1st call, it is a pointer to IdWinsock2.Stub_WSAGetLastError(), then after it is called it points to Winsock's actual WSAGetLastError() function.
  • either:
    • the IdWinsock2.InitializeWinSock() function has not been called yet, which occurs when creating a TIdStackWindows object, such as when any Indy component object is created at runtime, like your TIdTCPServer object.
    • the IdWinsock2.UninitializeWinSock() function has been called, which occurs ONLY during finalization of the IdStackWindows.pas unit, unless something outside of Indy calls it directly, which it shouldn't be!

So, it sounds like maybe something in your project is causing Indy to unload Winsock before the server has been deactivated.  Try putting a breakpoint on Indy's IdWinsock2.UninitializeWinSock() function and see if it is getting called while your server is active, and if so then look at the call stack to find out why it is being called.
Remy Lebeau
Lebeau Software - Owner, Developer
Internet Direct (Indy) - Admin, Developer (Support forum)