Using AppDomains to Parallelize Non-thread-safe DLL - c#

I have an unmanaged C++ DLL that my .NET application uses via p/invoke. The method that I need from this DLL is fairly time consuming and I would like to parallelize the method calls. The problem is that it uses a bunch of statics and globals, so it is not thread-safe (and can't be changed). My plan was to overcome this non-thread-safe issue by calling the unmanaged DLL from multiple AppDomains in parallel.
I can call the unmanaged code from the multiple AppDomains without any problems as long as I don't do it in parallel, but as soon as I make the calls in parallel, I get an AccessViolationException. I am using Parallel.For() to make the parallel calls.
Is it possible to make a non-thread-safe unmanaged DLL "thread-safe" by simply making the calls from multiple AppDomains?

Calling the native method from multiple AppDomain instances won't help you at all here. AppDomain boundaries don't apply to native DLL's and they won't provide any benefit

First and foremost: Load multiple copies of dll in same process
You'd have to make sure that all invocations within an AppDomain are on a single thread.
ParallelFor cannot make that happen, so you'd need to
manually parallelize (chunk up your loop for each thread/appdomain)
better (IMHO): write a wrapper function that will use a specific instance of your native dll (e.g. by using a reference to the AppDomain from threadlocal storage?).
Note that depending on the complexity of your situation (callbacks, use of global data in managed library) you might want to limit execution of each AppDomain to a specific CPU core (core affinity: see Begin/EndThreadAffinity). I might be a tad paranoid here :)

Wrap the C++ DLL in an EXE and parallelize process invocations (instead of running this code in threads or AppDomains). I had this problem with GeckoFX, which doesn't like threads, and this solution worked just fine. Of course, it's up to you to manage communication with these processes. I blogged about this some time ago.

Related

Executing code in main thread via dll injection

I need to inject a dll into the main thread of a process (otherwise my process will crash)
How would I go about doing this? My dll is in C++ obviously, my injection method though uses C# and CreateRemoteThread.
I've tried using std::thread(func) but that didn't work (of course it probably wouldn't since it most likely creates a new thread)
I don't know if this is a problem for my DLL or my injector, so all help and attempts to help is appreciated.
Your DllMain will run in the context of every thread... figure out which is the main thread.
Since you can't do much while the loader lock is held, create a callback with thread affinity (for example using SetTimer) and do all the work from that callback.
You can create the target process suspended and use CreateRemoteThread() for injection, but mind the following limitations:
You should copy the thread main routine for the remote thread to the address space of the target process.
This code cannot contain any external references (e.g. CRTL or direct WinApi calls). I would usually limit this code to loading of the DLL and either executing function from it, or relying on the DllMain to do the job you need. In order to call LoadLibrary and GetProcAddress methods, I obtain their addresses and copy structure containing this information to the target process and pass the address of the remote structure as an argument for the thread main routine in CreateRemoteThread(). You can use VirtualAllocEx() to allocate memory in the remote process,
Remote thread in this situation will be executed before main thread, including process and some Win32/64 initialization. Therefore, not every Win32 API is safe to call in this condition.
You can read more here: http://blogs.microsoft.co.il/pavely/2017/03/14/injecting-a-dll-without-a-remote-thread/

Any way to limit plugin rigths and resources?

We are developing and enterprise application with plugin-based architecture. Every plugin implements a contract that has a bunch of methods. All of those plugins are used in runtime by our core system and have their methods called permanantly. All of those calls must be async and in no way blocking.
We also give the ability for 3rd party developers to develop thier plugins. The problem is that this developers might implement some methods, which will not be async (by mistake or not). The worst case scenario is that this method will contain infinite loop.
We can put the call into separate thread, but after a couple of calls, those loops will take all the CPU time and could hung the system entirely.
Is there a way to ensure that those calls are not blocking and not resource critical?
P.S. We can drop any plugin at runtime if it's suspicious.

Calling two functions from a single Matlab dll at the same time

I have created a Matlab dll that includes two functions. Function1 takes 3-4 millisecond to run and Function2 takes around 1 second. I need to run Function1 in C# continuously and Function2 time to time. I experienced that when I run Function2, Function1 does not run continuously or it takes a lot more than 3-4 millisecond (something in the range of 2-3 second). Function1 returns to normal/fast state as soon as Function2 is completed. These are what I already tried:
I called Function2 in a separate Thread, with no luck! (Function1 is also running in a separate Thread).
I used backgroundworker instead of Thread (just in case), with no luck!
I created a separate dll just for Function2, and again I experienced same issue/delay/latency.
Does anyone have any idea/solution for this problem? Does Matlab run functions/code in single thread? If not, is there anyway to specify separate thread for Functions?
I appreciate any help.
It seems like your intuition is correct: Calls to Matlab libraries are executed sequentially, even if originating from multiple threads. Refer to the comments by Peter Webb under Creating C++ Shared Libraries and DLLs:
You can call the libraries from multiple threads, but only one thread can be active in a library at any time. The generated libraries are protected by semaphores, which only allow one user thread into the generated library at any one time. Other user threads that try to call into the shared library will block (wait) until the shared library is “free”.
[...]
The libraries protect themselves with semaphores. They do so because the underlying execution engine (the MCR) is not thread safe. This means that even if you could disable the semaphores, you wouldn’t want to, since you’d likely get incorrect results or program failures.
If you truly need parallelism, currently your best (and only) option is to use separate processes. If your client can speak any of the standard web protocols (HTTP or JSON) or Microsoft’s proprietry extended versions, it’s pretty simple to set up web-based WCF clients in separate processes using WCF. (Of course, your servers have to run on Windows machines in that case.) See my WCF post for details.

Aliased registration for a COM component to allow concurrent calls

There's a COM library I need to use that CANT be changed.
The Apartment State is STA and can't be switched to MTA without refactoring.
It's got two methods
Method One is a short operation
Method Two is a long running operation
I'd like to be able to make calls to Method One even if Method Two is in progress.
One approach I've considered is copying and altering the COM component's actual binary and registering it as a totally different COM component, then using an instance of this alias'd library to do the calls to Method Two so that the main instance is only responsible for calls to Method One.
I've tried just opening up the DLL in a hex editor and replacing the ProgID and ClsId, but that doesn't seem to be working. The registry entries I'm aware of look right, but when I add a reference in visual studio in order to generate my interop assembly, the generated library still has the old ClsId and calls to Method One still block until Method Two completes.
Any ideas on how I can make this work?
Is this approach totally misguided or am I on the right track?
Creating two STA threads to handle invocations to the component definitely allowed me to make concurrent calls.
The solution here actually was way simpler than the craziness I was talking about initially. I had considered this solution before, but thought I'd tried it and it hadn't worked. Something must have been wrong with my previous implementation.
Specifically, I've got two STA threads in which I'm instantiating my COM component, and then I'm passing invocation requests to these threads via a blocking collection. The calls specified in the request objects are made and the request objects are provided with responses which signals the calling thread that the call is complete.
#IgorTandetnik pointed me in this direction.

How to handle blocking synchronous external DLL methods

Recently I worked with an external dll library where I have no influence on it.
Under some special circumstances, a method of this third party dll is blocking and never returning.
I tried to work around this issue by executing this method in a new AppDomain. After a custom timeout, I wanted to Unload the AppDomain and kill all this crap ;)
Unfortunately, it does not work - as someone would expect.
After some time it throws CannotUnloadAppDomainException since the blocking method does not allow aborting the thread gracefully.
I depend on using this library and it does not seem that there will be an update soon.
So can I work around this issue, even if it's not best practice?
Any bad hack appreciated :)
An AppDomain cannot typically solve that problem, it's only good to throw away the state of your program. The real issue is that your thread is stuck. In cases like these, calling Thread.Abort() is unlikely to work, it will just get stuck as well. A thread can only be aborted if it is a "alertable wait state", blocking on a CLR synchronization object. Or executing managed code. In a state that the CLR knows how to safely clean up. Most 3rd party code falls over like this when executing unmanaged code, no way to ever clean that up in a safe way. A decisive hint that this is the case is AppDomain.Unload failing to get the job done, it can only unload the AppDomain when it can abort the threads that are executing code in the domain.
The only good alternative is to run that code in a separate process. Which you can kill with Process.Kill(). Windows do the cleanup. You'd use a .NET interop mechanism to talk to that code. Like named pipes, sockets, remoting or WCF. Plus the considerable hassle of having to write the code that can detect the timeout, kills the process, starts it back up and recovers internal state since you now restart with an uninitialized instance of that 3rd party code.
Do not forget about the real fix. Create a small repro project that reproduces the problem. When it hangs, create a minidump of the process. Send both to the 3rd party support group.
after reading this (scroll down the end to Blocking Issues) I think your only solution is to run the method in a different process - this might involve quite a bit of refactoring and/or a 'host' project (eg Console application) that loads the method in question and makes it easy to call (eg reading args from command line) when launching the new process using the Process class
You can always use background worker, no need to create a new appdomain. This will ensure that you have complete control over the execution of the thread.
However, there is no way to ensure that you can gracefully abort the thread. As the dll is unmanaged, chances are there that it may cause memory leaks. However, spawning a new thread will ensure that your application does not crash when the Dll does not respond.

Categories