473,396 Members | 2,011 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

AppDomains and static unmanaged variables

Our application environment consists of three basic layers:

1. Third-party unmanaged DLLs that were written before the CLR was invented
and maintain a significant amount of information (including memory
management and connection pooling constructs) as static variables which were
intended to scoped to the process.

2. Managed C++ assemblies (.NET 1.1) that wrap the unmanaged DLLs as nice
neat classes with managed interfaces.

3. ASP.NET 1.1 applications that call the managed assemblies.

When running just one ASP.NET web app, everything is fine, even with
high-volume multi-threaded access. But introduce a second web app in the
same AppPool, and eventually the state of the unmanaged DLLs in #1 become
corrupted. The only explanation I can come up with is that calling the
unmanaged DLLs from multiple AppDomains is breaking the assumption that the
original developers made that static variable are global to the process.

One workaround that seems to work is putting the web apps in different
AppPools, and thus different processes. Unfortunately, however, this is not
an option in some cases (for example, when writting an addin for
SharePoint).

I cannot recode the unmanaged DLL, as it was written by a third party. So
my only choice is to code some protection into my wrapper classes. For
example, is there a way to force all accesses to my wrapper class (or
wrapper assembly) to be marshaled over to a singleton AppDomain? Or perhaps
a way to force static variables to be global in a process again?

In the old COM days, when threading was our biggest problem, we has
apartment models to protect legacy code that code not handle
multi-threading. Is there nothing to protect legacy code that does not
understand about AppDomains?

Thanks!
Oct 4 '06 #1
6 4074
Stephen Walch wrote:
Our application environment consists of three basic layers:

1. Third-party unmanaged DLLs that were written before the CLR was
invented and maintain a significant amount of information (including
memory management and connection pooling constructs) as static
variables which were intended to scoped to the process.
Check.
>
2. Managed C++ assemblies (.NET 1.1) that wrap the unmanaged DLLs as
nice neat classes with managed interfaces.
OK.
>
3. ASP.NET 1.1 applications that call the managed assemblies.
Cool.
>
When running just one ASP.NET web app, everything is fine, even with
high-volume multi-threaded access. But introduce a second web app in
the same AppPool, and eventually the state of the unmanaged DLLs in
#1 become corrupted. The only explanation I can come up with is that
calling the unmanaged DLLs from multiple AppDomains is breaking the
assumption that the original developers made that static variable are
global to the process.
Unmanaged statics ARE global to the process. Managed statics are unique to
each AppDomain.
One workaround that seems to work is putting the web apps in different
AppPools, and thus different processes. Unfortunately, however, this
is not an option in some cases (for example, when writting an addin
for SharePoint).

I cannot recode the unmanaged DLL, as it was written by a third
party. So my only choice is to code some protection into my wrapper
classes. For example, is there a way to force all accesses to my
wrapper class (or wrapper assembly) to be marshaled over to a
singleton AppDomain? Or perhaps a way to force static variables to
be global in a process again?
To force all access to your code into a single AppDomain, you'd have to put
code in your managed layer to do the marshalling. This sounds complicated.

You unmanaged static varaible are already global to the process, so I
suspect that you've misdiagnosed the problem. Could it be that you have
managed static variables that need to be process-global as well?
In the old COM days, when threading was our biggest problem, we has
apartment models to protect legacy code that code not handle
multi-threading. Is there nothing to protect legacy code that does
not understand about AppDomains?
Unmanaged code cannot readily detect that AppDomains even exist. Unmanaged
statics still have process-global scope, and unmanaged code sees all threads
as being equal, with know knowledge that they might be coming from different
app domains.

-cd
Oct 4 '06 #2
You may be right that I have misdiagnosed the problem. My Managed C++
wrapper has statics that managed access to unmanaged statics. So if the
managed statics are scoped to teh AppDomain and the unmanaged statics are
scoped to the process, I have a big problem.

To use a concrete example, one of my managed classes has a static Monitor
instance that was supposed to make sure that no two threads attempted to
initialize the same unmanaged static state at the same time. Now I see that
is a two AppDomain scenario I actually have two Monitors and am not really
protecting the unmanaged state the way I thought I was.

So what is the answer to this? Is there any way to have a PROCESS GLOBAL
monitor, reference counter, memory handle, etc. in an unmanaged app?
"Carl Daniel [VC++ MVP]" <cp*****************************@mvps.org.nospam >
wrote in message news:eQ**************@TK2MSFTNGP03.phx.gbl...
Stephen Walch wrote:
>Our application environment consists of three basic layers:

1. Third-party unmanaged DLLs that were written before the CLR was
invented and maintain a significant amount of information (including
memory management and connection pooling constructs) as static
variables which were intended to scoped to the process.

Check.
>>
2. Managed C++ assemblies (.NET 1.1) that wrap the unmanaged DLLs as
nice neat classes with managed interfaces.

OK.
>>
3. ASP.NET 1.1 applications that call the managed assemblies.

Cool.
>>
When running just one ASP.NET web app, everything is fine, even with
high-volume multi-threaded access. But introduce a second web app in
the same AppPool, and eventually the state of the unmanaged DLLs in
#1 become corrupted. The only explanation I can come up with is that
calling the unmanaged DLLs from multiple AppDomains is breaking the
assumption that the original developers made that static variable are
global to the process.

Unmanaged statics ARE global to the process. Managed statics are unique
to each AppDomain.
>One workaround that seems to work is putting the web apps in different
AppPools, and thus different processes. Unfortunately, however, this
is not an option in some cases (for example, when writting an addin
for SharePoint).

I cannot recode the unmanaged DLL, as it was written by a third
party. So my only choice is to code some protection into my wrapper
classes. For example, is there a way to force all accesses to my
wrapper class (or wrapper assembly) to be marshaled over to a
singleton AppDomain? Or perhaps a way to force static variables to
be global in a process again?

To force all access to your code into a single AppDomain, you'd have to
put code in your managed layer to do the marshalling. This sounds
complicated.

You unmanaged static varaible are already global to the process, so I
suspect that you've misdiagnosed the problem. Could it be that you have
managed static variables that need to be process-global as well?
>In the old COM days, when threading was our biggest problem, we has
apartment models to protect legacy code that code not handle
multi-threading. Is there nothing to protect legacy code that does
not understand about AppDomains?

Unmanaged code cannot readily detect that AppDomains even exist.
Unmanaged statics still have process-global scope, and unmanaged code sees
all threads as being equal, with know knowledge that they might be coming
from different app domains.

-cd


Oct 4 '06 #3
[sorry, that last post had a lot of typos. let me try again...]

You may be right that I have misdiagnosed the problem. My Managed C++
wrapper has statics that manage access to statics in the unmanaged DLL. So
if the managed statics are scoped to the AppDomain and the unmanaged statics
are scoped to the process, I have a big problem.

To use a concrete example, one of my managed classes has a static Monitor
instance that was supposed to make sure that no two threads attempt to
initialize the same unmanaged static state at the same time. Now I see that
in a two AppDomain scenario, I actually have two Monitors and am not really
protecting the unmanaged state the way I thought I was.

So what is the answer to this? Is there any way to have a PROCESS GLOBAL
monitor, reference counter, memory handle, etc. in an managed app?

"Carl Daniel [VC++ MVP]" <cp*****************************@mvps.org.nospam >
wrote in message news:eQ**************@TK2MSFTNGP03.phx.gbl...
>Stephen Walch wrote:
>>Our application environment consists of three basic layers:

1. Third-party unmanaged DLLs that were written before the CLR was
invented and maintain a significant amount of information (including
memory management and connection pooling constructs) as static
variables which were intended to scoped to the process.

Check.
>>>
2. Managed C++ assemblies (.NET 1.1) that wrap the unmanaged DLLs as
nice neat classes with managed interfaces.

OK.
>>>
3. ASP.NET 1.1 applications that call the managed assemblies.

Cool.
>>>
When running just one ASP.NET web app, everything is fine, even with
high-volume multi-threaded access. But introduce a second web app in
the same AppPool, and eventually the state of the unmanaged DLLs in
#1 become corrupted. The only explanation I can come up with is that
calling the unmanaged DLLs from multiple AppDomains is breaking the
assumption that the original developers made that static variable are
global to the process.

Unmanaged statics ARE global to the process. Managed statics are unique
to each AppDomain.
>>One workaround that seems to work is putting the web apps in different
AppPools, and thus different processes. Unfortunately, however, this
is not an option in some cases (for example, when writting an addin
for SharePoint).

I cannot recode the unmanaged DLL, as it was written by a third
party. So my only choice is to code some protection into my wrapper
classes. For example, is there a way to force all accesses to my
wrapper class (or wrapper assembly) to be marshaled over to a
singleton AppDomain? Or perhaps a way to force static variables to
be global in a process again?

To force all access to your code into a single AppDomain, you'd have to
put code in your managed layer to do the marshalling. This sounds
complicated.

You unmanaged static varaible are already global to the process, so I
suspect that you've misdiagnosed the problem. Could it be that you have
managed static variables that need to be process-global as well?
>>In the old COM days, when threading was our biggest problem, we has
apartment models to protect legacy code that code not handle
multi-threading. Is there nothing to protect legacy code that does
not understand about AppDomains?

Unmanaged code cannot readily detect that AppDomains even exist.
Unmanaged statics still have process-global scope, and unmanaged code
sees all threads as being equal, with know knowledge that they might be
coming from different app domains.

-cd



Oct 4 '06 #4
"Stephen Walch" <sw****@online.nospamwrote in message
news:OO****************@TK2MSFTNGP05.phx.gbl...
[sorry, that last post had a lot of typos. let me try again...]

You may be right that I have misdiagnosed the problem. My Managed C++
wrapper has statics that manage access to statics in the unmanaged DLL.
So
if the managed statics are scoped to the AppDomain and the unmanaged
statics are scoped to the process, I have a big problem.

To use a concrete example, one of my managed classes has a static Monitor
instance that was supposed to make sure that no two threads attempt to
initialize the same unmanaged static state at the same time. Now I see
that
in a two AppDomain scenario, I actually have two Monitors and am not
really
protecting the unmanaged state the way I thought I was.

So what is the answer to this? Is there any way to have a PROCESS GLOBAL
monitor, reference counter, memory handle, etc. in an managed app?
I have a vagure recollection of an attribute that can be applied to statics
to make them process-global, but I can't find anything like that in .NET
docs, so I'm probably misremembering something.

A couple of options come to mind:
1. Move all of your statics into unmanaged code.
2. Use marshalling to send all calls to this code into a single AppDomain.
You'd have to store a reference to the singleton AppDomain somewhere that
every other AppDomain could get at it. For example, in an unmanaged static.

-cd
Oct 4 '06 #5
Hi Carl, Your helpful comments have pointed me in the right direction. I
have changed much of my "global" state management to use unmanaged static
variables and it has produced very encouraging results (i.e. no corruption).

I have not yet figured out how to move certain managed classes, such as
HashTable, to global state. I was able to declare a singleton instance

static gcroot<HashTable*g_table;

but it was only accessible from the AppDomain in which I initialized it. If
I try to access it from another AppDomain, I get the old "Cant pass a
GCHandle across AppDomains" message. Is there a better way? Or do I simply
need to find unmanaged equivalents to these classes?

"Carl Daniel [VC++ MVP]" <cp*****************************@mvps.org.nospam >
wrote in message news:OJ**************@TK2MSFTNGP02.phx.gbl...
"Stephen Walch" <sw****@online.nospamwrote in message
news:OO****************@TK2MSFTNGP05.phx.gbl...
>[sorry, that last post had a lot of typos. let me try again...]

You may be right that I have misdiagnosed the problem. My Managed C++
wrapper has statics that manage access to statics in the unmanaged DLL.
So
if the managed statics are scoped to the AppDomain and the unmanaged
statics are scoped to the process, I have a big problem.

To use a concrete example, one of my managed classes has a static Monitor
instance that was supposed to make sure that no two threads attempt to
initialize the same unmanaged static state at the same time. Now I see
that
in a two AppDomain scenario, I actually have two Monitors and am not
really
protecting the unmanaged state the way I thought I was.

So what is the answer to this? Is there any way to have a PROCESS GLOBAL
monitor, reference counter, memory handle, etc. in an managed app?

I have a vagure recollection of an attribute that can be applied to
statics to make them process-global, but I can't find anything like that
in .NET docs, so I'm probably misremembering something.

A couple of options come to mind:
1. Move all of your statics into unmanaged code.
2. Use marshalling to send all calls to this code into a single AppDomain.
You'd have to store a reference to the singleton AppDomain somewhere that
every other AppDomain could get at it. For example, in an unmanaged
static.

-cd


Oct 5 '06 #6
Stephen Walch wrote:
Hi Carl, Your helpful comments have pointed me in the right
direction. I have changed much of my "global" state management to
use unmanaged static variables and it has produced very encouraging
results (i.e. no corruption).
I have not yet figured out how to move certain managed classes, such
as HashTable, to global state. I was able to declare a singleton
instance
static gcroot<HashTable*g_table;

but it was only accessible from the AppDomain in which I initialized
it. If I try to access it from another AppDomain, I get the old
"Cant pass a GCHandle across AppDomains" message. Is there a better
way? Or do I simply need to find unmanaged equivalents to these
classes?
I guess you just need an unmanaged equivalent. I know that within the
implementation of the CLR there is the concept of app-domain neutral code
and data, but I don't think there's any way to make use of it from user
code.

-cd
Oct 5 '06 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
by: Mountain Bikn' Guy | last post by:
I need some advice on this. I am working on a fairly complex calculator app (C#) with lots of functions (and these functions in turn use math functions from an unmanaged C DLL). A calculation takes...
6
by: mflanagan | last post by:
I have unmanaged C++ program that will load a managed C++ dll and then call a function in that dll. The managed C++ routine will call some C# routines. The unmanaged C++ main program will make...
6
by: Pete Davis | last post by:
I'm confused about what precisely the limitations are on loading plugins in separate app domains. In all my previous apps that supported plugins, I've loaded them into the same domain as the app,...
0
by: Yevgeny Menaker | last post by:
I am struggling with the following: We have legacy classes written in C++ that are compiled to static libraries. Some of these classes are singletons. In order to make these classes available to...
12
by: Joe Narissi | last post by:
I know how to create and use static constructors, but is there a such thing as a static destructor? If not, then how do you deallocate memory intialized in the static constructor? Thanks in...
7
by: Boni | last post by:
Dear all, I have a global variable in the native code. I was assuming that I create a IJW CLI wrapper class and create an instance of this class in other appdomain, then the global variables will...
1
by: billr | last post by:
hi there, I hope that someone will be able to shed some light on little old confused me. We are developing an application which will be deployed onto a Terminal Server machine. The application...
4
by: Stephen Walch | last post by:
Our application environment consists of three basic layers: 1. Third-party unmanaged DLLs that were written before the CLR was invented and maintain a significant amount of information (including...
5
by: Jesper Schmidt | last post by:
When does CLR performs initialization of static variables in a class library? (1) when the class library is loaded (2) when a static variable is first referenced (3) when... It seems that...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.