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.
Related
I have a program in which even though the call stack has been processed fully it shows <Not Available> (like this). So I started debugging froze all other threads and ran the thread completely to find out that with an empty call stack it remained there and showed <Not Available> in the thread window of Visual Studio.
So my first question, what exactly is the lifetime of a managed thread (not thread object which is processed by Garbage Collection)?
My second question is how can I get this thread to be destroyed (AKA to garbage collection for objects). Tried GC.collect(), but apparently the garbage collector doesn't process CLR implemented managed threads.
Note I have gone through
Thread Object Lifetime( <- Thread Object, not thread), and
Killing Thread ( <- Killing or terminating a running thread, I am interested for an already finished thread, with an empty call stack), and a number of similar others...
Thanks !!
This is with regard to normal threads and not worker threads taken from the threadpool.
Update- I added a thread sleep to main thread and then added a breakpoint after that to find that the threads had been destroyed now.... I want to know how this is working.
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.
I'm working on an application that process pipelines in separate threads. During my tests I have seen that if a process is "lightweight" or the CLR determines that this is going to end quickly CLR recycle this thread rapidly and various units of work can share at the same time the same thread.
On the contrary if a process take's some time or has more load CLR open different threads.
To me all that difficult TLS Thread local storage programming.
In fact my application pipelines take some time to process and it seems that CLR is always assigning one managed thread for each other. BTW if in some case two pipelines share one managed thread they will collide because they use TLS variables.
After all that here comes the real question... Can I do the assumption that If a process takes some time/load it will always use it's own thread, or am I crazy doing that?
For what I have been reading managed threads in .net 3.5 is like acting with a kind of black box. So perhaps this question can never really be responded.
EDIT:
With process I am refereing to the dictionary definition A series of actions, changes, or functions bringing about a result an not the computer process you identify in task manager.
Can I do the assumption that If a process takes some time/load it will
always use it's own thread, or am I crazy doing that
Process always uses its own threads. It's not possible access other process's thread, not that I'm aware of.
Code run from a threadpool thread should not place anything in thread-local storage which it is not going to remove via finally block. If you need to ensure that any thread-local storage used by a piece of code will die after that code finishes executing, you need to explicitly either clean up the storage or run that code in its own thread.
When several threads are running the same piece of code, how CLR manages to keep them overstepping each other. Is it the AppDomain that manages these threads and define boundaries between different threads even though they might be acting on same code ( and possibly data)? If so how?
TIA
Simple; for method variables (excluding captured variables, iterator blocks, etc), the variables are on the stack. Each thread has a different stack. This is no different to a recursive method on a single thread - the method variables are separate and independent per call.
For objects on the heap... it doesn't!!. No boundaries; no protection. If you don't correctly synchronize etc, you will corrupt your data.
In short, this is your job.
It is an operating system implementation detail. Windows maintains the processor context for each thread. That context contains a copy of the state of the processor registers. Really important ones that matter to your question is EIP, the Instruction Pointer, and ESP, the Stack Pointer. The instruction pointer keeps track of the machine code instructions that are executed by the thread. The stack pointer keeps track of the activation frame of the currently executing method. Every thread has its own stack.
Since each thread has its own instruction pointer, they can each execute their own code, independent of other threads. Having their own stack ensures that threads cannot stomp each others local variables. Your machine has hundreds of threads running at the same time. They take turns executing code for a while on an available CPU core. It's the operating system's job to make that work, it saves the processor state in the thread context whenever it has been running for a while, or blocks, and it is time for another thread to get a turn. Resuming that thread simply involves copying the state back from the saved context to the processor. And it continues where it left off when it was interrupted.
Threading gets tricky once threads start to access memory that's shared by all threads. In a .NET program, that's anything that's stored on the garbage collected heap as well as any static variables. Having one thread that writes such memory and other threads reading the same memory needs to be orchestrated. The lock keyword is one of the primary ways to do this.
The relevance of an AppDomain is that each one has its own garbage collected heap and 'loader heap' (the place where static variable values are stored). Which prevents threads from stomping on each other completely. It is quite equivalent to a process, without the associated operating system cost of a process. Which is quite high on Windows. AppDomains are important on custom CLR hosts, like ASP.NET and SQL Server. They help isolating client requests so that, say, one web page request that bombs with an unhandled exception cannot also corrupt the state of all other requests.
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.