Can calling WSAStartup() from several threads cause a deadlock?

9k views Asked by At

I'm developing an app that has one TCP server and several UDP servers/listeners. Each server is a separate thread, same as the worker threads for established TCP connections. I'm calling WSAStartup() in each of the threads.

Sometimes, calling WSAStartup() hangs (it looks like a deadlock to me). Here is the stack trace:

  ntdll.dll!_KiFastSystemCallRet@0()  
  ntdll.dll!_ZwWaitForSingleObject@12()  + 0xc bytes 
  ntdll.dll!_RtlpWaitForCriticalSection@4()  + 0x8c bytes 
  ntdll.dll!_RtlEnterCriticalSection@4()  + 0x46 bytes 
  ntdll.dll!_LdrpGetProcedureAddress@20()  + 0x17d bytes 
  ntdll.dll!_LdrGetProcedureAddress@16()  + 0x18 bytes 
  kernel32.dll!_GetProcAddress@8()  + 0x3e bytes 
  vld.dll!03203723()  
  [Frames below may be incorrect and/or missing, no symbols loaded for vld.dll] 
  ws2_32.dll!CheckForHookersOrChainers()  + 0x22 bytes 
  ws2_32.dll!_WSAStartup@8()  + 0xa7 bytes 

This deadlock happens during the initialization faze. I see that the TCP server is started and that one TCP connection is established, while only one of UDP servers is started. The stack trace is from the function that should initiate the rest of UDP servers. My guess is that while I'm trying to init UDP sever and calling WSACStartup(), another tread is handling another socket operation, for example a new TCP connection and it's also calling WSAStartup()?

My question is whether calling WSAStartup() from several threads can cause this deadlock? Also I checked is the WSACleanup() called before the deadlock, and it isn't. The execution never reaches any of WSACleanup().

I'm aware that only one call to WSAStartup should be enough, yet calling WSAStartup() several times should not be a problem (MSDN]1): "An application can call WSAStartup more than once if it needs to obtain the WSADATA structure information more than once." Hence, I would like to establish whether this deadlock is caused by WSAStartup() or something else.

4

There are 4 answers

3
Warren Young On

You don't have to call WSAStartup() multiple times at all. Once per program is fine.

2
wilx On

I think that Luke is right. You cannot call WSAStartup() in DllMain() or in initializers of global/static variables. Change your code so that it does not happen.

2
Andrey On

WSAStartup doesn't actually lead to LoadLibrary of any kind, so I don't feel like it is a loader lock case.

Instead, it is obvious that windows API is being trapped in your case (term trap is better here, because hook has other meaning in Windows).

Thus, I believe that the problem is not in concurrent use of WSAStartup, but in side effects of third party traps over original Windows API functions in your process. I think, you need to clean up your environment from any external influence (api traps from your side or from anti-virus software, whatever).

By the way, make sure that each thread of yours provides WSAStartup with its own separate copy of WSADATA output parameter

0
Eftiquar On

The WSAStartup function typically leads to protocol-specific helper DLLs being loaded. As a result, the WSAStartup function should not be called from the DllMain function in an application DLL. This can potentially cause deadlocks. Dllmain is called in DLL loader critical section which is primary reason of this deadlock.
For more details : http://msdn.microsoft.com/en-us/library/windows/desktop/ms742213%28v=vs.85%29.aspx