我正在开发一个具有一个 TCP 服务器和多个 UDP 服务器/侦听器的应用程序。每个服务器都是一个单独的线程,与建立 TCP 连接的工作线程相同。我在每个线程中调用 WSAStartup()。
有时,调用 WSAStartup() 会挂起(对我来说这看起来像是一个死锁)。这是堆栈跟踪:
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
这种死锁发生在初始化 faze 期间。我看到 TCP 服务器已启动并建立了一个 TCP 连接,而仅启动了一个 UDP 服务器。堆栈跟踪来自应该启动其余 UDP 服务器的函数。我的猜测是,当我尝试初始化 UDP 服务器并调用 WSACStartup() 时,另一个线程正在处理另一个套接字操作,例如一个新的 TCP 连接,它也在调用 WSAStartup()?
我的问题是从多个线程调用 WSAStartup() 是否会导致这种死锁?我还检查了死锁之前调用的 WSACleanup() ,但事实并非如此。执行永远不会到达任何 WSACleanup()。
我知道只调用一次 WSAStartup 就足够了,但多次调用 WSAStartup() 应该不是问题(MSDN] 1):“如果需要获取 WSADATA 结构信息,应用程序可以多次调用 WSAStartup不止一次。” 因此,我想确定这个死锁是由 WSAStartup() 还是其他原因引起的。