jocull
jocull

Reputation: 21155

msvcr71.dll crashing IIS 7 app pool on Windows Server 2008 w/ ASP.NET 4

I am working on a project that requires a C library that I have wrapped with managed code. The C library is compiled for 32-bit and I've figured out that it requires msvcr71.dll. Problem is that this DLL does not come stock with Windows Server 2008 in the SysWOW64 directory for whatever reason.

I've copied the DLL from SQL Management Studio on the system, and I can verify that it works in a standalone EXE on the server. There is nothing preventing it from working.

HOWEVER... when I link it into my ASP.NET application and ensure both my library's DLL and msvcr71.dll are in my /bin directory the application pool for my site falls out from under me. werfault.exe fires up, eats a bunch of CPU and RAM, then goes away and leaves me this mostly useless log in the Event Viewer.

Then the application pool restarts and waits to fail again. It's running with .NET 4 in Integrated mode. The site is based on MVC 3.

Faulting application name: w3wp.exe, version: 7.5.7601.17514, time stamp: 0x4ce7a5f8
Faulting module name: ntdll.dll, version: 6.1.7601.17725, time stamp: 0x4ec49b8f
Exception code: 0xc0000374
Fault offset: 0x000ce6c3
Faulting process id: 0x998
Faulting application start time: 0x01cd753eb1fcd760
Faulting application path: C:\Windows\SysWOW64\inetsrv\w3wp.exe
Faulting module path: C:\Windows\SysWOW64\ntdll.dll
Report Id: 7b54f020-e132-11e1-a34d-404094d3cf82

What on earth is going on here? I'd love to have the DLL linked right into my ASP.NET site but I am on the brink of just writing a proxy application... I'd like to avoid that hack if possible. Thanks.

Side note All of this works perfectly fine on my local machine. It's only on the server that I'm having real trouble getting it linked into IIS.

UPDATE

This appears to be an interop problem when running inside of IIS, particularly with string methods... I am looking into it now...

http://blogs.msdn.com/b/asiatech/archive/2009/12/24/net-application-may-crash-on-windows-2008-when-calling-function-from-native-c-dll.aspx

Upvotes: 2

Views: 3177

Answers (1)

jocull
jocull

Reputation: 21155

Hate to answer my own question, but it needs a solution recorded for everyone else. The core problem I had here was not actually msvcr71.dll (thought in the end I did end up recompiling the original C source for the library in question against version 10 of the C runtime msvcr100.dll since it is included in Windows Server 2008 by default.

I am still running the library against x86. However the real problem here is that there is some kind of memory management bug (or feature, you decide) that causes IIS 7 to crash when doing Interop on P/Invokes with strings in .NET. I think it was intended as a security feature... who knows.

Check out the article listed in the question update above for partial details on this:

http://blogs.msdn.com/b/asiatech/archive/2009/12/24/net-application-may-crash-on-windows-2008-when-calling-function-from-native-c-dll.aspx

The specific library I am working with is for Shapefiles from GIS tools if you are that curious.

http://shapelib.maptools.org/

This made some sense to me, but my library is written in C and not C++. Regardless, neither language is my strong suit and I could not find a CoTaskMemFree method that existed in the C compiler. It's probably my own fault, but I really didn't have time to learn and rewrite some ancient C code.

I figured out that I could just not marshal a string back using .NET methods and instead do it manually from IntPtr to prevent IIS from crashing.

Here's my original import:

    [DllImport("shapelib.dll", CharSet = CharSet.Ansi)]
public static extern string DBFReadStringAttribute (IntPtr hDBF, int iShape, int iField);

...and here's what I had to change it to:

    [DllImport("shapelib.dll", CharSet = CharSet.Ansi)]
public static extern IntPtr DBFReadStringAttribute (IntPtr hDBF, int iShape, int iField);

That change by itself stopped the application from crashing. Then I had to create this sort of hack to pull the strings out. I know this has to be far from optimist but it's the best I could do for now.

Here's what I ended up doing in the end...

public static string DBFReadStringAttribute(IntPtr hDBF, int iShape, int iField)
{
    IntPtr dataPtr = _DBFReadStringAttribute(hDBF, iShape, iField);
    string output = Marshal.PtrToStringAnsi(dataPtr, 255); //255 is the supposed max length for DBF databases
    int idx = output.IndexOf('\0');
    string strData;
    if (idx > 0)
        strData = output.Substring(0, idx).Trim();
    else
        strData = "";

    return strData;
}

[DllImport("shapelib.dll", CharSet = CharSet.Ansi, EntryPoint = "DBFReadStringAttribute")]
private static extern IntPtr _DBFReadStringAttribute (IntPtr hDBF, int iShape, int iField);

Additional note

For whatever reason Marshal.PtrToStringAnsi(dataPtr) did not retrieve the string properly (it would come out corrupted). I had to set a maxlength and parse it myself.

Upvotes: 1

Related Questions