Terminate a Thread running code I can't control - c#

I am doing a project where I am loading several assemblies during runtime, for each of those assemblies I use reflection to find some specific classes, instantiate them and calling their methods. All this is working fine, but for some of the calls the process encounters a stack overflow which terminates my entire program. I don't have any control over the source code of the assemblies I am loading so I cant change the code I'm executing.
What I have tried to solve the problem:
I assign a thread to do the invocation of the methods and tried to
abort the thread after a timeintervall(I know that this is bad
practice but I cant change the code to terminate friendly). This
however doesn't work, I think the thread is to busy "stackoverflowing"
to handle the Abort-call.
Ive tried reducing the actual memory the thread has access to, this is not even a solution because you cant catch the stackoverflow-exception so my program terminates anyway (just quicker)
Questions:
Can a thread be to busy to be aborted? Is there some way to abort a thread that is having this behaviour?
How can we call code (that we don't have any control over) in a good way?
Thanks in advance!

The recommended procedure in case of "opaque code" is to actually fork a new process and start it. That way you gain two benefits:
If it fails by itself, it's isolated and won't take your main application down as well.
You can safely kill it and it won't cause as much trouble as an aborted thread.

Related

What would be a use case for Thread.Sleep(Timeout.Infinite)?

I happened to lay my eyes on an intellisense tool tip regarding the parameter passed to System.Threading.Thread.Sleep(int millisecondsTimeout), saying something like "(…) Specify System.Threading.Timeout.Infinite to block the thread indefinitely". And I am intrigued.
I can understand why one might include short inactive delays within a possibly endless loop, thus yielding processing power to other executing threads when no immediate action in the sleeping thread is required, although I typically prefer implementing such delays with EventWaitHandlers so that I can avoid waiting a full sleeping delay if I signal the thread to gracefully end its execution from a different thread.
But I cannot see when I might need to suspend a thread indefinitely, and in a way that, as far as I can tell, can only be interrupted through a rather ungraceful Thread.Abort()/ThreadAbortException pair.
So what would be a working scenario where I might want to suspend a thread indefinitely?
It is a pretty long story and I have to wave my hands a bit to make it understandable. Most programmers think that Thread.Sleep() puts the thread to sleep and prevents it from executing any code. This is not accurate. Thread.Sleep(Infinite) is equivalent to Application.Run(). No kidding.
This doesn't happen very often in real life, it is mostly relevant in custom hosting scenarios. Getting code to run on a specific thread is in general an important feature to deal with code that is not thread-safe and the major reason why Application.Run() exists. But Windows exposes another way to do at a much lower level, the underlying api for this is QueueUserAPC(). The .NET analogue of this function is BeginInvoke().
This requires the thread to co-operate, just like it does when it calls Application.Run(). The thread must be in an "alertable wait state", executing a blocking function that can be interrupted. The CLR does not execute the sleep by itself, it passes the job to the CLR host. Most hosts will simply execute SleepEx(), passing TRUE for the bAlertable argument. The thread is now in a state to execute any requests posted by QueueUserAPC(). Just like it will be when it is actively executing inside the Application.Run() dispatcher loop.
The kernel feature is not otherwise exposed at all in the framework. It is the kind of code that is very hard to get right, re-entrancy bugs are pretty nasty. As most programmers that were bitten by Application.DoEvents() or a poorly placed MessageBox.Show() can attest. It is however a valid scenario in a custom hosting scenario. Where the host can get C# code to run on a specific thread, using this mechanism. So it is possible to pass Infinite because the designers did not want to intentionally disable this scenario. If this is made possible at all by the host author then they'd let you know about it. I don't know of a practical example.
More practically, you do use this feature every day. It is the way that System.Threading.Timer and System.Timers.Timer are implemented. Done by a thread inside the CLR which is started as soon as you use any timer, it uses SleepEx(INFINITE, TRUE) at its core.
You can use .Interrupt() to wake a sleeping thread (causing ThreadInterruptedException in the code that was calling .Sleep(), which can be caught and handled), so this provides a mechanism to say "sleep until someone prods you". I'm not saying it is necessarily the best mechanism for this, but: it may have uses for you.

Task equivalent that can be killed at once

I want to run a long running opeartion in the background.
The requirements are:
The operation should run async to the calling thread.
The calling thread can wait on the operation to complete and obtain its result
Upon timeout, the operation should be aborted at once.
I would have used task, but there is no mechanism that I know of to kill the task dead cold.
Cancel token is not suitable for me, I would only kill a task if it gets stuck for unknown reason - (a bug) , this is a fail-safe mechanism.
Needles to say if the task is stuck, there is no use in requesting cancel.
Same goes for BackgroundWorker.
Is there anything more elagent than using a shared object between the calling thread and a background thread?
There is nothing more elegant than using a shared object, since using a shared object is the elegant way of doing this :)
You cant provide a generic way of killing a task safely: Since the killer thread does not have any clue of what the killee is doing when trying to kill it, this would potentially leave your object model in a "corrupted" state.
Thread.Abort() has been created to do that the cleanest way possible: By throwing an exception (which allows "finally" statements to dispose used resources, or running transactions disposal on killed thread). But this method can make the code throw an exception in unexpected location. It is highly not recommended.
nb: Thread.Abort() does not work in any case (example: wont work if your thread is running native code via a P/Invoke for instance)
Thus, the elegant solution is to write clean code, which can decide when it wants to be killed (via a cancellation token).
nb2: The ultimate "Thread.Abort()" which will work in any case, and which which will keep things isolated: Create a new AppDomain, run your killable code in this AppDomain (via remoting), and call AppDomain.Unload() when you want to stop everything.
This is a quite extreme solution, though.
The only way to kill a thread 'dead cold' that I know of is Thread.Abort, however, you will see a lot of answers to this related question, Killing a Thread C#, indicating that it is generally bad practice to use it, except in rare occasions.
Another option is to avoid trying to kill the task dead cold and implement better error handling in your task such that it gracefully handles exceptions and situations where it 'gets stuck'.

Multi-thread debugging with VisualStudio and WebBrowser Windows.Forms controls

We're creating a few threads in a Windows.Forms solution.
We've also got a BrowserControl (yup, it's OAUTH) and of course I'm finding issues with debugging -
Cross-thread operation not valid: Control 'xxForm' accessed from a
thread other than the thread it was created on
And yet I am calling 'correctly'
xxForm.Show()
by ensuring it's wrapped in an invoke call
.Invoke(new MethodInvoker())
and still I get the thread issue. I can do everything else (Focus, BringToFront) it's the Show that errors.
Moreover, the GUI never gets the browser response and shows. In the VS debugger I get the above threading erropr (apartment state of background thread == MTA). When run as an EXE the same code has a threading aparement of STA and the GUI will never show when debugging, but if I run the EXE directly, there's no threading issue, the browser control just never responds to input.
Spo the questions are:
Why the different behjaviour in VS / EXE?
How do I debug in VS?
Does the BrowserControl play ok with multiple threads?
Update
YES I KNOW there's no code - it's too long. I'll see what I can do.
Also please read the question before posting an answer. I am invoking the background thread on the UI thread. That's not the issue. This has NO EFFECT on the result. I'll down vote answers that recommend that.
Also some hope - I've searched for many hours. It's linked the the message pump. Unless the message pump is running the DocumentCompleted event isn't received.
Update 2
Best I manage is pseudo code:
Program:
startWorkQueue
LoadForm (don't show)
Thread1:
addToQueue
Thread2:
readFromQueue
ShowForm (on occasion)
Now the ShowForm method is on a Windows.Form control.
Within this any call is made via an Invoke, so that despite the 2nd thread making the call the ShowForm, the actual .Show() etc etc calls are on the UI thread.
So what am I missing? I just don't understand why there's a cross thread exception....
Ok I've found out what was going on and I'll post here for reference.
I hope it helps someone in the future.
We had some different constraint to the vanilla Forms applications - our Forms were created on the Main thread but had Show() called on a different thread. We also don't have a starting UI - we sit in the background and sometimes react to events with UI prompts.
As such a number of issues hit us. Rather than list them all I'll detail our takeaways:
Application.Run
If decide NOT to Show a Form at the start of your application… then you'll need to consider threads carefully (see Form.Show notes)
Form.Show
This does all resource allocation etc, NOT the Load/ctor
Performs handle creation / resource allocation
Handle creation
Hwnd
If we attempt to access certain Form properties before it has Show(n) then you'll need to create a handle manually (or an Exception is created)
• As easy as if (!IsHandleCreated) { CreateHandle(); }
HOWEVER
This create the control/form
Therefore the control/form is created on the Thread that calls the Handle create
This must be the same UI thread (STA) as the Main function
• Otherwise much weirdness occurs
SO
You aren't restricted by what to do with Application.Run
You can access properties in .Show (but you may need to create a handle first)
You can call Show from a different thread, but ensure the handle is ONLY created on the main thread
I hope it helps, I can provide more details on our specific problems if need be.
Various aids that helped included displaying ManagedThread AND ProcessId in the log and scouring MSDN.
Since the code has not been pasted, I would like to remind you that in WinForms, the UI elements should be accessed only on the UI thread. Any other thread apart from UI thread should not be updating the UI elements directly.

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.

How do I suspend all threads after my program crashes?

I have an unhandled exception handler. It shows a nice GUI and allows users to send an error report. Users can even leave their name and phone number and things, and our support department calls them back. Works well, looks good, makes customers less angry. In theory, anyway.
The problem is that my application uses background threads, and the threads don't seem to care if an exception was thrown on, say, the GUI thread (which makes sense), and just continue their work. That eventually results in a WER dialog poping up if the user lets my custom exception handler window stay open long enough, making it look like the error handler itself crashed.
I don't have access to the thread objects in the scope of the exception handler, so I can't suspend them. Making the thread objects globally accessible is not a solution either. My workaround for now is to use something like Globals.Crashed = true; in my exception handler, and to have my thread methods check that property at every loop iteration. Not perfect, but it minimizes the damage.
Does anyone know a less-hacky method? Is my approach wrong? Do I have to do it like WER does and launch an external program that suspends the main program and shows the error UI?
If you have an unhandled, unknown exception, you can assume that ANYTHING has happend and that your program might fail to do even the most simple thing. Consider e.g. the case that it has consumed all available memory - then you won't be able to send the error report either, because it probably requires memory to be allocated.
A good approach is to write a separate small application that just does the error reporting. That application can pick up the details to report from a file. That way your unknown exception handler would:
Dump the info to a file in the temp directory.
Start the error reporting app with the file name as an argument.
Terminate the failing process, before it does something stupid.
The temp file should be removed by the error reporting app.
You could track all your threads in a global Collection object, so that when your handler executes, it could simply iterate through the collection object and abort the threads there.
Take a look at the code in this question, Suspend Process in C#, you'll need to tweak it so as to not suspend your GUI thread and any that aren't background ones you've started, but it should do the trick.
The better option, however, is to try and launch your error report GUI as a separate process, passing any required information to it, and then kill the original process from your unhandled exception handler, rather than allowing anything to run in a potentially corrupt state.

Categories