Search code examples
c#c++asp.net-web-apithread-safetyappdomain

StackOverflow exception when running static class from a WebAPI project - works fine when run from a console application


I have a 3rd party library that wraps a C++ dll - let's call it LegacyAPI. This wrapping library is a static class with imported methods and is not thread safe.

I have my own wrapper library that wraps around this 3rd party wrapper (to provide logging etc). Let's call it LegacyAPIWrapper

So, this is all supposed to be used in a web api - lets call it WebAPI

My WebAPI controller action invokes my LegacyAPIWrapper. It goes through some of the methods (including calls to that unsafe LegacyAPI), and fails with StackOverflow exception - always at the same method from the LegacyAPI.

To troubleshoot that, I have created a console application - ConsoleApp. It calls my LegacyAPIWrapper the same way as the WebAPI does - and it works OK!

I have enforced STA Thread on my web api controller methods as described here. http://ryanhaugh.com/archive/2014/05/24/supporting-sta-threads-in-web-api/ Also, the wrapper methods are also attiributed with STAThread attribute.

I have introduced some additional logging logic

this.Logger.Debug($"Apartment state: [{Thread.CurrentThread.GetApartmentState()}]. Thread ID: [{Thread.CurrentThread.ManagedThreadId}]. Thread State: [{Thread.CurrentThread.ThreadState}]");

that shows that right from where the LegacyAPIWrapper is initiallized to where it throws error, we are consistenly within the same Thread, that it is an STA and that it is a running thread.

Apart from that, I have also tried invoking the LegacyAPIWrapper in a separate AppDomain as suggested here

https://bitlush.com/blog/executing-code-in-a-separate-application-domain-using-c-sharp

But it did not change anything. And, by 'anything', I also mean that we are still on the the same thread (before the Isolated is called and within the Isolated) - so perhaps I'm doing something wrong?

Any hint will be appreciated.


Solution

  • I have 'solved' it - it turned out that it was a matter of the stack size requirement of the 3rd party app.

    When hosted on the w3wp process, the stack available was too small - which is why it worked when hosted as console app.

    w3wp.exe stack size is 256kb (it used to be 1MB prior to 2003)

    https://blogs.msdn.microsoft.com/tom/2008/03/31/stack-sizes-in-iis-affects-asp-net/

    The resolution

    1. In File Explorer, browse to C:\Windows\SysWOW64\inetsrv\
    2. Right-click on w3wp.exe and select Properties > Security > Advanced > Owner > Edit > Change owner to > Administrators > OK > Ok > OK
    3. Give [Admin-User] full permission on w3wp.exe
    4. Press the Start button on the Windows toolbar and in Search programs and files, type “cmd”
    5. Right-click cmd.exe and select “Run as Administrator”
    6. Type: "C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\vcvarsall.bat”
    7. Type: cd C:\Windows\SysWOW64\inetsrv
    8. Type: EDITBIN /STACK:1048576 w3wp.exe