How do you handle a thread that has a hung call? - c#

I have a thread that goes out and attempts to make a connection. In the thread, I make a call to a third party library. Sometimes, this call hangs, and never returns. On the UI thread, I want to be able to cancel the connection attempt by aborting the thread, which should abort the hung call to the third party library.
I've called Thread.Abort, but have now read that Thread.Abort only works when control returns to managed code. I have observed that this is true, because the thread never aborts, and I've been sitting on Thread.Join for ten minutes now. What should I do with this hung thread? Should I just null the reference and move on? I'd like to be as clean as possible--

Random thought: I wonder if you could write a second assembly as a small console exe that does this communication... launch it with Process.Start and capture results either via the file system or by intercepting stdout. Then if it hangs you can kill the process.
A bit harsh, maybe - and obviously it has overheads of spawning a process - but it should at least be possible to kill it.

This function in your third-party library doesn't have a timeout or cancel function? If so, that's pretty poor design. There's not going to be any pretty solution here, methinks...
Unfortunately, there's no way you're going to get around it, short of using the Win32 API to kill the thread manually, which is certainly not going to be clean. However, if this third-party library is not giving you any other options, it may be the thing to do. The TerminateThread function is what you'll want to use, but observe the warning! To get the thread ID to pass to this function, you have to use another Win32 API call (the Thread class doesn't expose it directly). The approach here will be to set the value of a volatile class variable to the result of GetCurrentThreadId at the start of the managed thread method, and then use this thread ID later to terminate the thread.

Not sure if this will do it or be acceptable, but its worth a shot.
[DllImport("kernel32.dll")]
private static extern bool TerminateThread (Int32 id, Int32 dwexit);
From the documentation
TerminateThread is a dangerous function that should only be used in the most extreme cases. You should call TerminateThread only if you know exactly what the target thread is doing, and you control all of the code that the target thread could possibly be running at the time of the termination. For example, TerminateThread can result in the following problems:
If the target thread owns a critical section, the critical section will not be released.
If the target thread is allocating memory from the heap, the heap lock will not be - released.
If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL.

Managed threads can't directly stop native threads. So if the call is blocked in native code then the best you can do is have the managed thread check then terminate once it returns. If it never returns, maybe there's a version of the call with a timemout?
If not, killing the thread (through win32) is not usually a good idea...

Not a good solution to ever wait on a thread (in any language) indefinitely, especially if you are making external calls. Always use a join with a timeout, or a spin lock that monitors the state of a shared atomic variable until it changes, or you reach a timeout. I'm not a C# guy, but these are all sound concurrency practices.

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'.

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.

Watch dog for blocking function call

I have a closed-source API for some hardware sensor that I use to query that sensor. The API comes as DLL that I use through C# interop. The API's functions are blocking. They usually return error values but in some cases they just won't return.
I need to be able to detect this situation and in that case kill the blocked thread. How can this be done in C#?
The thread they're being invoked on is created through a BackgroundWorker. I'm looking for a simple watch dog for blocking function calls that I can set up before calling the function and reset when I'm back. It should just sit there and wait for me to come back. If I don't, it shall kill the thread so that 1) the API is freed up again and no thread of my application is still hanging around and doing anything should it eventually return and 2) I can take other recovery measures like re-initialising the API to continue working with it.
One approach might be to set up a System.Threading.Timer before the API call to fire after a certain timeout interval, then dispose the Timer after the call completes. If the Timer fires, it'll fire on a ThreadPool thread, and you can then take appropriate action to kill the offending thread.
Note that you'll need to P/Invoke to the Win32 TerminateThread API, since .NET's Thread.Abort() won't work if you're blocked in unmanaged code.
Also note that it's very unlikely your process will be in a safe state after forcibly killing a thread, as the terminated thread might be holding synchronization objects, might have been in the middle of mutating shared memory state, or any other such critical operation. As a result of terminating it, other threads may hang, the process may crash, data may be corrupted, dogs and cats might start living together; there's no way of being sure what'll happen, but chances are it'll be bad. The safest approach, if possible, would be to isolate usage of the API into a separate process that you communicate with via some remoting channel. Then you can kill that external process on demand, as killing a process is a lot safer than killing a thread.

Need help understanding _set_security_error_handler()

So , I've been reading this article:
http://msdn.microsoft.com/en-us/library/aa290051%28VS.71%29.aspx
And I would like to define my custom handler.However, I'm not sure I understand the mechanics well.What happens after a call is made to the user-defined function ( e.g. the argument of _set_security_error_handler() ) ? Does the program still terminate afterward ? If that is the case, is it possible to terminate only the current thread(assuming that it is not the main thread of the application).AFAIK, each thread has its own stack , so if the stack of a thread gets corrupted, the rest of the application shouldn't be affected.
Finally, if it is indeed possible to only terminate the current thread of execution, what potential problems could such an action cause?
I'm trying to do all this inside an unmanaged C++ dll that I would like to use in my C# code.
The documentation states:
"After handling a buffer overrun, you should terminate the thread or exit the process because the thread's stack is corrupted"
Given this statement, it would seem that you could indeed simply kill the thread. However, you are correct to ask what problems this could cause. The docs for TerminateThread discuss the following problems that can arise from killing a thread:
If the target thread owns a critical section, the critical section will not be released.
If the target thread is allocating memory from the heap, the heap lock will not be released.
If the target thread is executing certain kernel32 calls when it is terminated, the kernel32 state for the thread's process could be inconsistent.
If the target thread is manipulating the global state of a shared DLL, the state of the DLL could be destroyed, affecting other users of the DLL
See here: http://msdn.microsoft.com/en-us/library/ms686717(VS.85).aspx
The only "safe" thing to do in this circumstance is to exit the process.

Categories