How to deal with exceptions on separate threads in an external dll? - c#

I'm loading in a dll that spawns a few threads within itself. Every now and then the program crashes with an unhandled exception. I can't wrap all my library calls in try/catch statements because the exceptions are being thrown on separate threads, and I don't have access to the library's source to debug/fix the bad error handling. I'd like the program to keep doing other things when these exceptions happen, is there a graceful way to handle these exceptions? Or is the only thing I can do to do a global catch all exceptions method?

If you load the DLL into a separate appdomain, you should be able to isolate exceptions generated with a AppDomain.UnhandledException, but, be aware that this is not fool proof and there are certain situations where it will still take your process out too and there is nothing you can do about it (stack overflow, out of memory etc).
The best you can do in that case is load them in a separate process completely with some kind of dll communication harness and using some form of remoting to talk to that process.

I would recommend to implement a separate process (EXE) which your application launches and which in turn loads the DLL.
This allows you to kill/restart the process whenever need be...
I see several options on how to communicate - for example:
you could use COM (if you implement it as an out-of-process COM server)
you could use shared memory (very high performance, see this for a walkthrough and this for a .NET 2 wrapper)
IF the method must be compatible with several Windows versions THEN I would refrain from using anything "networky" for the IPC (since some come with a desktop firewall).

Related

Prevent native C++ DLL crashing C# App

We have a c# WPF app and we use a 3rd party SDK with a native C++ DLL, we call the methods with DllImport attributes.
Unfortunately code is not that great and that C++ DLL crashes our C# app.
Is there an elegant and efficient way to isolate the calls to the C++ DLL so their exceptions don't crash our app? We are getting a stream of images and data so it needs to be fast.
We use WCF to offload some operations in a windows service, so we have an infrastructure to do this, but I don't think it will be fast enough to transfer data and image buffers to/from it.
Would a different AppDomain be a good choice? Any examples how to do this?
thanks
Its probably the right behaviour to terminate the app in this situation. If you have control over the DLL I would consider handling its exceptions differently
From memory, i believe (in early versions of .Net) you could just catch via ExternalException class:
Note : .NET v4 and above it disables the delivery of certain exceptions by default
To reenable this i 'believe' you can just edit your manifest or use an attribute, take a look at
legacyCorruptedStateExceptionsPolicy Element
HandleProcessCorruptedStateExceptionsAttribute Class
a similar crash occured to me not long ago.I think first you should resove the native dll error . There is no way that you can use to catch an exception from a native code.
The only way to make sure the C++ DLL does not crash your C# process is to move it to another process which you can restart if it crashes.
You can wrap the C++ DLL in a separate application / service and communicate with your C# application via named pipes to transfer the image data. You will also need some kind of heart beat to detect if the wrapper crashed and restart it as needed.
We implemented this solution for a microscope which came with an ActiveX component that kept crashing our application. This approach worked well and was fast enough.
AppDomains don't provide isolation for native assemblies as they use unmanaged memory, due to this I'm not sure if an access violation in a secondary app domain will bring down your whole process.
I'm guessing that your problem is due to state corruption. So before trying to outboard the service you can try catching those exceptions.
How to handle AccessViolationException
So long as the library itself can recover, you might be OK. Worth giving a go.

C# Restricting DLL's to only one instance

I essentially want to make an api for an application but I only want one instance of that dll to be running at one time.
So multiple applications also need to be able to use the DLL at the same time. As you would expect from a normal api.
However I want it to be the same instance of the dll that the different applications use. This is because of communication with hardware that I don't want to be able to overlap.
DLLs are usually loaded once per process, so if your application is guaranteed to only be running in single-instance mode, there's nothing else you have to do. Your single application instance will have only one loaded DLL.
Now, if you want to "share" a "single instance" of a DLL across applications, you will inevitably have to resort to a client-server architecture. Your DLL will have to be wrapped in a Windows Service, which would expose an HTTP (or WCF) API.
You can't do that as you intend to do. The best way to do this would be having a single process (a DLL is not a process) which receives and processes messages, and have your multiple clients use an API (this would be your DLL) that just sends messages to this process.
The intercommunication of those two processes (your single process and the clients sending or receiving the messages via your API) could be done in many ways, choose the one that suits you better (basically, any kind of client/server architecture, even if the clients and the server are running on the same hardware)
This is an XY-Problem type of question. Your actual requirement is serializing interactions with the underlying hardware, so they do not overlap. Perhaps this is what you should explicitly and specifically be asking about.
Your proposed solution is to have a DLL that is kind of an OS-wide singleton or something like that. This is actually what you are asking about; although it is still not the right approach, in my opinion. The OS is in charge of managing the lifetime of the DLL modules in each process. There are many aspects to this, but for one: most DLL instances are already being shared between every process (mostly code sections, resources and such - data, of course, is not shared by default).
To solve your actual problem, you would have to resort to multi-process synchronization techniques. In Windows, this works mostly through named kernel objects like mutexes, semaphores, events and such. Another approach would be to use IPC, as other folks have already mentioned in their respective answers, which then again would require in itself some kind of synchronization.
Maybe all this is already handled by that hardware's device driver. What would be the real scenarios in which overlapped interactions with the underlying hardware would have a negative impact on the applications that use your DLL?
To ensure you have loaded one DLL per machine, you would need to run a controlling assembly in separate AppDomain, then try creating named pipe for remoting (with IpcChannel) and claim hardware resources. IpcChannel will fail to create second time in the same environment. If you need high performance communication with your hardware, use remoting only for claiming and releasing resource by another assembly used by applications.
Mutex is one of solution for exclusive control of multiple processes.
***But Mutex will sometimes occur dead lock. Be careful if you use.

Handle access violations in COM interop

My managed app is using COM interop. Unfortunately there is a bug in the COM component that causes access violation. When the bug is hit, the whole app crashes, the handler attached to AppDomain.CurrentDomain.UnhandledException didn't get a chance to run. I wonder if there is a way to handle the AV, show a friendly message to the user and recover the managed app?
There is NO way to "handle" an Access Violation.
Depending on the component you are using and how it is implemented even isolating it inside a second AppDomain might still crash your process - AppDomains are "only" a .NET-thing, from the native perspective of the OS they are NOT isolated.
IF you have some problematic component you can always make your usage of it more robust by using the following approach:
Create a process (EXE) which wraps the usage of that component and exposes an API (for example via any IPC mechanism). You can then start that EXE as a separate process (from your main EXE) and use it... IF you need to kill that component after a certain time and/or when some condition is met you can always kill that "wrapper EXE" from your main EXE... depending on the specific component it might even be useful to implement some special "cleanup code" (possibly in a separate thread) within that "wrapper EXE" which gets executed when you need to kill that "wrapper EXE".
Since you are implementing this in .NET you can even have that "wrapper EXE" as "embedded resource" in your main executable and start it even from RAM without writing it to the filesystem.
There is fundamentally no way to "handle" an Access Violation. You have no way to know which memory the COM component has trashed before it sent the AV.
The only thing you can do with a component like this is to try to run it in a separate AppDomain. That way, if it crashes, it only crashes one AppDomain.

Prohibit starting a form in third-part dll plugin (c# service)

I have the a service, that loads some dlls and starts a function in each dll. Each dll contains some rules, that can be also developed by our clients (something like plugin system). The problem is, that clients can theoretically add forms to be called inside dlls. So the goal is to disallow that, or, at least block such dlls.
The only method I can imagine now is call each dll in a separate thread and kill it after some timeout.
But I think it is not so nice.
Please advice me a better method. Thankx.
The best way to deal with plug-ins is to "sandbox" each one of them in an individual app domain. This way you can safely react to their execution errors, unload them if you need to, and manage them in whatever ways you like. But most importantly for this question, you can monitor their loading of assemblies using this event hook. If you see them loading a DLL that you do not want to allow, you can simply throw an exception. Your code would catch the exception, clean up the app domain, and optionally send the clients a warning for trying to do something that is not allowed.
The only downside to this approach is that it is rather non-trivial to implement.
It is VERY hard problem to protect server from third party code that you need to execute.
I would recommend reading on SharePoint sandbox approach (i.e. http://msdn.microsoft.com/en-us/library/ff798382.aspx) which tries to solve this and related issues.
As SLaks said - you implicitly trust code by simply executing it. Unless you expect code to be outright evil you may be better of by simply logging how long calls take (and maybe time out if possible) and provide your client with this information. Since it seems like client creates the code for themselves it is unlikely that code will be explicitly made non-functional.
Other interesting issues outside showing a Form:
stack overflow exception (easy to create, hard to handle)
while(true); code that never returns control
access to native code if full trust enabled.
You could always use reflection to inspect their code and ensure that certain namespaces and classes (e.g. System.Windows.Forms.*) are not referenced or used.
SQLCLR restricts what is allowed to be used/referenced in assemblies installed as SQLCLR extensions, and that appears to be done that way: http://msdn.microsoft.com/en-us/library/ms403273.aspx

How to host Plug-ins safely with .NET 2.0

I am writing a chess game which allows two programs compete, the player needs to write a DLL and expose a function to tell the main application where his player will move next, suppose the function looks like this
public static void MoveNext(out int x, out int y, out int discKind);
The player's DLL can be written using C# or C++.
In the chess game application, I start a new thread to call the function that the player's DLL exposed to get where he will move in a turn, and I start a timer to prevent the player timeouts, if a player timesout i will kill the corresponding thread by following APIs
thread.Abort();
thread.Join();
I have the following issues as described below:
The thread cannot be killed with 100% assurance (it depends on the player's code)
During test I found that, if the player uses a deep recursions (and if there is memory leak in the player's program), the memory usage of the host application will increase and then the host application will be terminated without any exceptions.
Are there any techniques, ideas or methods that can handle the above issues?
From this CodeInChaos suggested to load player's DLL into separate domain and then unload it when necessary, I am not sure if it still works for the unmanaged DLL (C++) and if it will cause a low efficiency?
An unhandled exception in their AppDomain will still cause your program to terminate in .Net 2.0. You get a chance to respond to the exception through an event handler but not the ability to handle it.
Your best bet is to use processes for the kind of isolation you're looking for.
If you can ensure your plugin DLL's are always managed code, then you have the option of createing a new application domain in your main application logic and loading the assembly containing the plugin into that domain.
This then gives you the option of trapping unhandled excpetions in that specific app domain and you then have the option of Unloading that whole app domain. That way you can cope with other peoples application plugins misbehaving and throwing exceptions. you also gain the option of specifying partial trust to further restrict what a plugin can do.
However this will not help if you cannot enforce the use of managed code plugins, and the earlier option of a set of seperate processes would be more apropriate.
Reading your post agin it seems you have some quality issues with the plugins you have to use. If you must cope with such buggy plugins I would take the previous advice and go with seperate processes.

Categories

Resources