0
votes

Does anyone have any idea on what the following crash means or how to debug it?

Faulting application name: MyServer.exe, version: 0.0.0.0, time stamp: 0x53d885f1

Faulting module name: WS2_32.dll_unloaded, version: 0.0.0.0, time stamp: 0x4ce7ca25

Exception code: 0xc0000005

Fault offset: 0x000007fefe67a0af

Faulting process id: 0xcbc

Faulting application start time: 0x01cfabbc216f52c2

Faulting application path: [Path]/MyServer.exe

Faulting module path: WS2_32.dll

Report Id: 61efadce-17af-11e4-8301-001517d9c80a

This happens when I link my exe (unmanaged C++) with a managed C++ dll (exposed via dllexport). From windbg, it seems that the crash is happening right after loading all the modules, before it even gets to main:

(51d4.5e50): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. +0x1a0af: 000007fefe67a0af ?? ??? 0:000> kP Child-SP RetAddr Call Site 000000000020dc80 00000000002a2700 <Unloaded_WS2_32.dll>+0x1a0af 000000000020dc88 00000000002a2701 0x2a2700 000000000020dc90 00000000`00000000 0x2a2701

The managed C++ dll is a DNS library which eventually calls into WS2_32.dll underneath.

The weird thing is that another exe that uses the same managed C++ dll is working fine, and I didn’t see any obvious differences between the sources/headers files that would cause this different behavior. If I comment out either (1) the code that references this managed dll, or (2) everything else in my exe EXCEPT the code that references the managed dll, then the crash also does not occur. The fact that (2) works tells me that at least all the dll dependencies should be in the working directory.

This happens only on Windows Server 2008 R2. I am using .Net 4.5.

Anyone has any pointers?

3
You are making a call into a DLL that is unloaded. Such a call always crashes with an AVE. How ws2_32.dll got unloaded is impossible to guess from the question. Tends to be an environmental problem with shoddy anti-malware on the top of the list.Hans Passant
Thanks for the reply Hans. It turned out to be unrelated to anti-malware, and has to do with another DLL that my application is trying to load which is unintentionally unloading the WS2_32.dll.Richard Liu
Shoddy DLL that does unspeakable things to other DLLs was second on my list. Malware :)Hans Passant

3 Answers

5
votes

I had a similar problem involving a native application that used many DLLs of which one was managed. The fact that the application was failing to get to main suggested that a DLL's DllMain was returning FALSE. However, I didn't know which one although the log in the event viewer showed a similar error message to that provided by the OP. Fortunately for me, the application only failed on new build PCs. Actions performed to try and debug the problem:

  • Use loader snaps to trace the DLL loading process. In conjunction with WinDbg, this gave an indication of which DLL failed by virtue of the fact that the bunch of DLLs being uninitialised included all but one that had had its initializer run. It did not show the actual return value of each DLL's DllMain though.
  • Use Dependency Walker's profiling option to trace the return values of DllMains. However, this hung so was not fruitful.
  • Capture the startup using ProcMon on both machines and compare the traces. This was more fruitful and showed divergent behaviour between the two after examining the registry entry HKLM\Software\Microsoft\SQMClient\Windows\CEIPEnable. In the working case, CEIPEnable was 0. In the failing case, CEIPEnable was 1. This turns out to be the Windows Customer Experience Improvement Program as mentioned by nop. Disabling this allowed the application to be launched on the failing machine.
  • Use AppVerifier to trap those DLLs (when run under the debugger) that were calling WSAStartup in their DllMain. This indeed flagged the suspected DLL (as well as others). This behaviour is contrary to MSDN's advice as noted by Richard.

Further observations:

  • If I enabled CEIP on the good machine, the application still launched successfully. Therefore, other factors must be involved in causing the failure.
  • Microsoft Japan have an article about this issue in which disabling CEIP is listed as a workaround. The linked article is in Japanese but Google can translate it.
  • The managed DLL did not seem to be the issue.

I hope someone finds this answer useful. I would not have solved my problem had nop's answer not been here.

1
votes

I was recently faced with the exact same symptoms (and same callstack), but no other DLL was messing with ws2_32.dll, so I'm just putting this here in case someone else has the same issue: in my case the culprit was Windows' Customer Experience Improvement Program, which, if enabled, made my application crash. Just disable it and you'll be fine.

I have no in-depth explanation for this behavior, only that the "Sqm" you see in the function names are related to this service and that a different code path will be taken inside ws2_32.dll when the Customer Experience Improvement Program is disabled (there is a function that checks Sqm opt in that's called during WSAStartup).

0
votes

I found the reason after some debugging. I was able to reduce the problem down to two API calls:

void __cdecl main(int argc, __in_ecount(argc)  char* argv[])
{

    UNREFERENCED_PARAMETER(argc);

    UNREFERENCED_PARAMETER(argv);

    HRESULT hr = TS_STATUS_OK;

    /***** A *****/
    hr = InitializeDllA();
    ASSERT(SUCCEEDED(hr)); 

    /***** B *****/
    hr = InitializeDllB();

    ASSERT(SUCCEEDED(hr));   
}

Both DLLs are dependent on WS2_32.dll. But what happened is that in the DllMain() for A, there is a call to WSAStartup() which ended up unloading the WS2_32.dll. Stack trace from WinDBG confirms this after setting breakpoints on module load/unloads:

0:000> k
Child-SP          RetAddr           Call Site

00000000`001ae0c8 00000000`771f2773 ntdll!ZwUnmapViewOfSection+0xa 
[e:\obj.amd64fre\minkernel\ntdll\daytona\objfre\amd64\usrstubs.asm @ 484]

00000000`001ae0d0 00000000`771f3b5a ntdll!LdrpUnloadDll+0x3c6 [d:\win7sp1_gdr\minkernel\ntdll\ldrapi.c @ 1672]

00000000`001ae1f0 000007fe`fd822dd5 ntdll!LdrUnloadDll+0x4a [d:\win7sp1_gdr\minkernel\ntdll\ldrapi.c @ 1743]

00000000`001ae220 000007fe`fee5a0af KERNELBASE!FreeLibrary+0x1d [d:\win7sp1_gdr\minkernel\kernelbase\module.c @ 1193]

00000000`001ae250 000007fe`fee54a68 WS2_32!Ws2SqmGetFileVersionInfo+0x12f [d:\w7rtm\minio\sockets\winsock2\sqmlib\ws2sqm.c @ 308]

00000000`001ae2c0 000007fe`fee473df WS2_32!Ws2SqmInit+0xd678
00000000`001ae510 000007fe`d7c01042 WS2_32!WSAStartup+0x2fd [d:\w7rtm\minio\sockets\winsock2\ws2_32\src\startup.cpp @ 301]

There is a MSDN article on this: WSAStartup function.

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 a application DLL. This can potentially cause deadlocks. For more information, please see the DLL Main Function.

Which explains why the program crashes before main() is entered, since the crash occurred during DLL loading.