Saturday, February 14, 2009

Run Win32 application in its own application pool

A handful of ThinClient customers periodically can not login to ThinClient . The server-side log indicates that an access violation occured when the back-end code tried to check whether ThinClient feature has been enabled in the license. We could not duplicate the issue in house until one of my colleague tried to login to ThinClient while running automation test against server webadmin ASP pages.

The following is a simplified version of architectural layers for ThinClient and WebAdmin ASP.


IIS is used to host WCF service, ASP .NET application, and classic ASP pages. The license object is a global singleton written in native C++ and resides in native C++ layer.

At the beginning, it was very hard for me to associate WCF service layer, ASP .NET application, and classic ASP pages together. Since in my opinion, ASP pages should definitely run in a different process from those .NET applications. So I attached WinDBG to w3wp and ran the test case again. WinDBG broke into access violation exception right away. From the stack trace, I could see COM layer code at the bottom of the stack and managed C++ code at the top of the stack. Since I tried to login to ThinClient when the exception occurred, it completely made sense to see managed C++ code on the stack. However, the COM layer code used by classic ASP also on the stack did not make any sense. Even more interesting, when WinDBG broke into the exception, WCF service, ASP .NET, and classic ASP pages all stopped. It seems to me that they were running in the same process. Then I checked IIS configuration and found out that all of them were running in the same application pool. With the help of my colleage, we found out the application pool only used one worker process. After increasing the number of worker process to 5, we ran the test case again. The issue happened much less. Then we moved WCF service and ASP .NET into a different application pool so that both .NET applications are in the same pool and classic ASP in another one. Everything works fine since then.

Confused by what I have seen, I looked for some explanation. Unfornatunely, I did not find any formal document on whether .NET and Win32 applications could run in the same application pool. However, from some blog articles, email threads, and the document on application pool, it seems that .NET applications benefit from the application pool. Multiple .NET applications running in the same application pool not only reduces fixed overhead on the memory, but also improves the performance and stability. To shield its variables from being visible to all other applications in the same pool, .NET applications are seperated by AppDomain. For a specific .NET application, its variables are only visible inside its AppDomain. However, for Win32 applications, since there is no such a boundary for them. A global or static variable in one Win32 application would be visible to all other applications in the same application pool. Therefore, a Win32 application should run in its own application pool.


1 comments:

  1. Since the following user seems to have the similar issue, I copy/paste the whole email for reference.

    Based on your description, my understanding on your problem is that you have an ASP.NET web application which uses a managed C++ component library that act as a wrapper of an unmanaged c++ dll. This application works well
    when there is only single web application work in the Application Pool, but get messed state management when running multiple web applications in the same application pool(IIS), correct?

    As you mentioned that the C++ unmanaged dll uses some static variables to manage global connection pool(or other states), I think this should be the cause of the problem. As for ASP.NET(or other .net framework/clr based
    application), it is running at AppDomain based boundary, that means global variables(static class members in .net applications) is only visible in its own AppDomain, not in the entire host process(which is different from the variable sharing scope for win32 application---process based scope).

    For your scenario, in IIS6, all the ASP.NET applications (which use the same App Pool) will be hosted in the same worker process, therefore, if you've used any unmanaged c++ code which use global variables, they'll be
    accessible by all the applications in the worker process no matter they're in the same AppDomain or not. Therefore, I'm wondering whether it is possible that you'll configure those applications to use separate application pool(in IIS) if they'll access the same win32/c++ global variables? So far this is the only means I can get to prevent the win32/ c++ global variables to be accessed by multiple applications.
    ReplyDelete