5

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.

MD XF
  • 7,860
  • 7
  • 40
  • 71
Misko Mare
  • 113
  • 2
  • 4
  • This is no answer to your question, but did you consider using boost asio (http://www.boost.org/doc/libs/1_43_0/doc/html/boost_asio.html)? I had a much easier time solving problems like yours with that library. – nabulke Aug 05 '10 at 17:57
  • Nikolai, I used the boost before and like it. Since I started this app with WinSock I would like to get to the bottom of this issue. Just to curious I guess:) – Misko Mare Aug 05 '10 at 18:30
  • Did you look at your other threads' call stacks? – Collin Dauphinee Aug 05 '10 at 18:33
  • 3
    Looks like you have a deadlock involving the loader lock; you should look at the other threads and see if they are calling LoadLibary, GetProcAddress, etc, particularly if it is happening in one of their DllMain functions. – Luke Aug 05 '10 at 19:04
  • dauphic, I'm using VS 2005. I don't how to check other threads' stacks in VS 2005. I believe that newer versions of VS should have that option. – Misko Mare Aug 05 '10 at 20:28
  • in VS2005 - "Debug > Windows > Threads", mini dump would even be better, but it would make SO similar to customer support :) – Andrey Aug 05 '10 at 21:26
  • The deadlock is not caused by calling `WSAStartup` from multiple threads. It is caused by calling it from `DllMain` (or whatever you decided to call your DLL entry point). This has been pointed out by @Luke already, but since you decided to ignore it I thought I'd bring it up again. – IInspectable Dec 11 '14 at 15:42

4 Answers4

4

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

Community
  • 1
  • 1
Eftiquar
  • 41
  • 1
3

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

Warren Young
  • 40,875
  • 8
  • 85
  • 101
  • 1
    Imho, question states clearly that topic starter has read this part of MSDN and instead of solution to "avoid" the problem (which is definitely a good solution) - he is trying to find the root cause. – Andrey Aug 05 '10 at 21:24
  • It's like the old joke: "Doctor, it hurts when I do this." "So don't do that, then." – Warren Young Aug 05 '10 at 21:33
  • 2
    If you are using AppVerifier, calling `WSAStartup` only once per process will not suffice. It's good practice to have each thread initialize the Windows Sockets, and uninitialize them when finished. This is particularly true if you cannot know ahead of time, which is the final thread to exit. – IInspectable Dec 26 '14 at 15:45
1

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.

wilx
  • 17,697
  • 6
  • 59
  • 114
  • I'm working on a standalone application and I'm using system DLLs, hence I don't have a DLLMain(). All my calls to WSAStartup() are in the thread functions: http://msdn.microsoft.com/en-us/library/ms686736(VS.85).aspx PS. here is the list of additional libraries: - ws2_32.lib - strsafe.lib - shell32.lib – Misko Mare Aug 05 '10 at 20:40
  • Take a closer look at the list of DLLs loaded into "release" version of your application (w/o profilers, leak detectors, etc). Chances are that one of those DLLs is trapping windows functions. SysInternals' Process Explorer will help you a lot. – Andrey Aug 05 '10 at 21:33
0

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

Andrey
  • 4,216
  • 1
  • 23
  • 31
  • 1
    Are you sure it doesn't do a **LoadLibrary** call? – notbad.jpeg Jul 31 '14 at 19:45
  • You're right, I don't remember why I thought that way back then, but it actually can load helper DLLs according to MSDN - thus loader lock might be an issue. I still think, looking at the stack, root cause is in a trap that intercepted WSAStartup. – Andrey Aug 06 '14 at 00:22