Looks like I'm trying to do something that other's haven't run into again. Atleast, from Google searching it seems like this is pretty unique.
I have a server running with a directory full of dlls. Each dll is used to process a certain type of order and managed by different people. When an order comes in, there is a table that determines which dll to spin up, run it and then spin it down (free from memory).
The process we started with was:
Create an AppDomain
Load needed dll into the domain
Run the code we need
Unload the AppDomain
The issue we had with this was the server would run out of memory or we would get "token errors". I think the issue is that we call some 3rd party pascal dlls I don't think are getting freed.
We updated our the process to:
Create an AppDomain on process load
Load the dll into this "global" AppDomain
Run the dll's code
This got rid of our memory issues and we have recieved zero token errors. However, when we want to move a dll from our test server to our production server we have to kill the whole service, and then the dlls are not locked in memory. Then reprocess any orders that died with the service and any that came in while the service was down.
I've worked with the group and tried to unload the AppDomain, but once it is unloaded it doesn't just free dll's that are running, it basically kills the whole domain. I've considered moving this dll loader to it's own System.Process, so that the OS can clean up the memory when the process ends. However, I'm not sure how to have one Process run code in another Process. This plan seems like basic OS security features would prevent it because virus' would have a heyday.
Does anyone have an idea how we can run dll's in an AppDomain and then having them unlocked from memory so that they can be updated? (Without creating and disposing many AppDomain because they don't seem to clean everything up.) It would be great to have a memory pool that I can nuke and but .NET isn't about manual memory management.
Related
I have a ASP.NET (C#) website that uses a third party DLL to process the data that the users POST via a web form. The call is pretty straightforward:
string result = ThirdPartyLib.ProcessData(myString);
Once in a blue moon this library hangs and (according to my hosting provider logs) consumes 100% of CPU. The website is hosted on a shared hosting, so I have no access to the IIS or event logs. When this happens, my website is automatically stopped by the hosting provider performance monitor, and I have manually switch it back on.
Now, I know that the right thing to to is investigate the problem and fix (or replace) the DLL. But as it's third-party software, I am unuable to fix it, and their support is not helpful at all. Moreover, I can't reproduce the problem. Replacing the library is a pain too.
Is there a way in C# to detect when this DLL starts consuming 100%CPU and kill the process automatically from my ASP.NET code?
You cannot "detect" if the current process is hanging because as the caller of a method (third party or not) you're simply not in control until it returns.
What you can do is move the call to the third party library into a separate executable and have it output its result via the standard output (you can simply use Console.WriteLine(string) for this).
Once you've done that, you can start a separate Process that runs this executable, read the result via StandardOutput and use WaitForExit(int) to wait a certain amount of time (maybe a few seconds) for the process to finish. The return value of WaitForExit() tells you if the process actually exited. In case it didn't, you can Kill() it and move on without IIS worker process hanging as a whole.
I read the concept about Application Domain in .NET. However, I don't know when to use it. A application domain is working as a thread in a process. A process will have more than or equal one application domain. However, I can deploy a process with multi-threading without using application domain.
Anyone can tell some examples to use it in practice. There are source code for examples are good. And I wonder that there are any Microsoft's applications to use this technology.
Thanks.
If you load a dll in your main AppDOmain you can't unlod it. But if you load the .dll in an AppDOmain you can unload the AppDomain and so unload the dll. Like that you can load and unload dll.
And with Addin I saw that you can load plugin in AppDomain with security, in order that the plugin can not compromise the main software security.
I would like to explain the usage of AppDomains in a real world design problem from one of my earlier project.
Basically that project is a port scanner for some information. So we had 6 ports, and we are suppose to scan 6 ports in parallel. Of course we could have used threads, but then isolation would not be possible at all. We wanted every port functionality i.e scanning should be completely isolated and even its data storage and other functionality to be independent.
So what we did was, we used AppDomain concept in loading on of our dll which does this scanning job and few more (proprietary logics) into 6 AppDomains we had created for each port. Infact, this dll spawns more thread internally to do various jobs once you scan the port for some data. Hence we have completely isolated each port scanning and when user wants to stop scanning for one of the port (via UI selection) then we just have to gracefully unload this AppDomain.
Hope it was some help to you :)
MSDN really gives a clear picture here of what AppDomains are actually for: http://msdn.microsoft.com/en-us/library/system.appdomain.aspx
Application domains, which are represented by AppDomain objects, help provide isolation, unloading, and security boundaries for executing managed code.
Use application domains to isolate tasks that might bring down a
process. If the state of the AppDomain that's executing a task becomes
unstable, the AppDomain can be unloaded without affecting the process.
This is important when a process must run for long periods without
restarting. You can also use application domains to isolate tasks that
should not share data.
If an assembly is loaded into the default application domain, it
cannot be unloaded from memory while the process is running. However,
if you open a second application domain to load and execute the
assembly, the assembly is unloaded when that application domain is
unloaded. Use this technique to minimize the working set of
long-running processes that occasionally use large DLLs.
I'm implementing an application which will load and execute 3rd party code.
While .NET Sandboxing is fine, I can't find a way to prevent code from starting new threads.
This is a problem because AFAIK we can't enumerate and abort them safely to unload the sandbox AppDomain - we have to exit the whole process.
How could I ban Thread.Start, or (better) whitelist/blacklist specific CLR APIs?
You would need to create a scripting environment rather than run compiled code. In this environment you could parse out unsupported/unwanted keywords.
http://msdn.microsoft.com/en-us/library/ms974577.aspx
http://osherove.com/blog/2004/2/17/make-your-net-application-support-scripting-a-practical-appr.html
http://www.codeproject.com/KB/library/Dotnet_Scriptor.aspx
There might be some way of limiting permissions of code running within an AppDomain, is this what you are talking about with Sandboxing?
Good example of use of AppDomain
You could potentially force unloading of an AppDomain if "bad stuff" was occuring with cpu and memory.
more recently in .net 4 I have noticed but not investigated HostProtection Permissions ...
System.Security.Permissions
hostprotectionattribute
=== EDIT ===
It looks like CLR Hosting with Security Permission being set would be the way to go. Links...
What is CLR hosting?
http://msdn.microsoft.com/en-us/library/hbzz1a9a(v=vs.90).aspx
http://msdn.microsoft.com/en-us/library/h846e9b3(v=vs.90).aspx
http://msdn.microsoft.com/en-us/library/system.security.permissions.securitypermission(v=vs.90).aspx
Is there a way to release an object that was accessed using late-binding (i.e. created by the Activator.CreateInstance() method)?
I have an application that transforms files from one format to another. The assemblies that perform these translations live in a folder in my application directory.
When the application first starts up, I can delete these assemblies from the translation folder without any errors. However, once I process a document through the application (and have bound to one of the translation assemblies using late-binding), I can no longer delete the translation assemblies. At this point, I'm receiving an error message stating that the file is "in use by another application".
Is there a way to "release" the late-bound object in my application once I'm finished using it?
Once an assembly is loaded into an application domain it'll remain until the app domain shuts down.
To get around this load the assembly into it's own application domain, for example:
AppDomain app = AppDomain.CreateDomain("PlugInDomain");
ObjectHandle objectHandle = app.CreateInstanceFrom(assemblyPath,
"MyNamespace.MyComponent");
MyComponent component = (MyComponent) objectHandle.Unwrap();
// do stuff
// Now kill app domain, assembly can be overwritten after this.
AppDomain.Unload(app);
Once an assembly is loaded into the executing AppDomain, it cannot be unloaded (regardless of whether it is creating via reflection with Activator.CreateInstance).
The recommended approach here is to implement a secondary AppDomain with a lifetime that can unload when it wants to dispose the assemblies.
There are tons of examples, but here is one:
http://www.dotnet247.com/247reference/msgs/28/142174.aspx.
Since managing the lifetime of secondary AppDomains can be a pain, as an alternative, if you are using ASP .NET and are looking to load many dynamic assemblies, you can check when your current AppDomain becomes saturated with dynamically loaded assemblies by binding to the AppDomain.CurrentDomain.AssemblyLoaded event and keeping count, then requesting the hosting environment recycle the current AppDomain when it hits a critical number (say 500) like:
HostingEnvironment.InitiateShutdown();
Application domains allow applications to be unloaded separately. My question is how unloading an apllication can crash another application. Any example?
In theory, App Domains are completely isolated from each other (even though you may run several App Domains in one process, they act as separate processes), so this shouldn't be possible.
Are you asking theoretically, or are you actually experiencing crashes?
I assume you mean AppDomain when saying Application.
Pure managed code should unload correctly (but not all finalizers might execute)
But buggy native inter-op can of course still crash the process.