We usually throw exception when invalid input is passed to a method or when a object is about to enter invalid state. Let\'s consider the following example
I downloaded the SSCLI code and started poking around. The code is difficult for me to follow (mostly because I am not a C++ or ASM expert), but I do see a lot of hooks where the aborts are injected semi-synchronously.
That is just to name a few. What I wanted to know was how asynchronous aborts were injected. The general idea of hijacking the instruction pointer is part of how it happens. However, it is far more complex than what I described above. It does not appear that a Suspend-Modify-Resume idiom is always used. From the SSCLI code I can see that it does suspend and resume the thread in certain scenarios to prepare for the hijack, but this is not always the case. It looks to me that the hijack can occur while the thread is running full bore as well.
The article you linked to mentions that an abort flag is set on the target thread. This is technically correct. The flag is called TS_AbortRequested and there is a lot of logic that controls how this flag is set. There are checks for determining if a constrained execution region exists and whether the thread is currently in a try-catch-finally-fault block. Some of this work involves a stack crawl which means the thread must be suspended and resumed. However, how the change of the flag is detected is where the real magic happens. The article does not explain that very well.
I already mentioned several semi-synchronous injection points in the list above. Those should be pretty trivial to understand. But, how does the asynchronous injection happen exactly? Well, it appears to me that the JIT is the wizard behind by the curtain here. There is some kind of polling mechanism built into the JIT/GC that periodically determines if a collection should occur. This also provides an opportunity to check to see if any of the managed threads have changed state (like having the abort flag set). If TS_AbortRequested is set then the hijack happens then and there.
If you are looking at the SSCLI code here are some good functions to look at.
There are many other clues. Keep in mind that this is the SSCLI so the method names may not match exactly with call stacks observed in production (like what Josh Poley discovered), but there will be similarities. Also, a lot of the thread hijacking is done with assembly code so it is hard to follow at times. I highlighted JIT_PollGC because I believe this is where the interesting stuff happens. This is the hook that I believe the JIT will dynamically and strategically place into the executing thread. This is basically the mechanism for how those tight loops can still receive the abort injections. The target thread really is essentially polling for the abort request, but as part of a larger strategy to invoke the GC1
So clearly the JIT, GC, and thread aborts are intimately related. It is obvious when you look at the SSCLI code. As an example, the method used to determine the safe points for thread aborts is the same as the one used to determine if the GC is allowed to run.
1Shared Source CLI Essentials, David Stutz, 2003, pg. 249-250