ThreadAbortException isn't re-thrown after being caught (RyuJIT) - by Kevin Gosse

Status : 

 


2
0
Sign in
to vote
ID 3131699 Comments
Status Active Workarounds
Type Bug Repros 0
Opened 4/4/2017 9:10:27 AM
Access Restriction Public

Description

As the documentation states, a ThreadAbortException should automatically be re-thrown at the end of a catch block: https://msdn.microsoft.com/en-us/library/system.threading.threadabortexception(v=vs.110)

>  ThreadAbortException is a special exception that can be caught, but it will automatically be raised again at the end of the catch block

Take the following program:

        static void Main(string[] args)
        {
            var mutex = new ManualResetEventSlim();

            var t = new Thread(() =>
            {
                while (true)
                {
                    try
                    {
                        if (!mutex.IsSet)
                        {
                            mutex.Set();
                        }

                        // Do some stuff

                        Thread.Sleep(100);
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine("Exception: " + ex.Message);
                    }
                }
            });

            t.Start();

            // Wait for the thread to start
            mutex.Wait();

            t.Abort();

            Console.ReadLine();
        }

When compiled in x64 and run with RyuJIT, the ThreadAbortException isn't re-thrown at the end of the catch block, thus resulting in an infinite loop.

It seems to be related to RyuJIT, because the bug disappears when using the legacy JIT:

<useLegacyJit enabled="1" />

Reproduced with Visual Studio 2017, .NET 4.6.2, compiled in Release and x64. 
Sign in to post a comment.
Posted by briansul on 4/11/2017 at 3:48 PM
Thank you Kevin for providing us with your test case where you discovered this incorrect behavior.

I have investigating this issue further and have discovered that your code sample, just happens to hit a case where to work around an older issue we declined to raise the thread abort.

The code that you provided hit this case and making any small modifications to your test case will correct the issue.
This issue is also already corrected in our next update of the RyuJIT compiler for the Desktop.

If you modify the test case and add any code after the try{} catch{} and before end of the loop then the program re-raise thread abort correctly.
If you modify the test case and add any code after the while { and before the start of the try region then the program re-raise thread abort correctly.

The CLR has to be quite careful when deciding whether to raise thread abort.

In general once a thread has been marked with the ThreadAbort tag we will try to raise the thread abort exception at every legal opportunity that we can.
This include whenever you enter or exit the VM code, such as the PInvoke call to Sleep in your test case, and returning after executing exception handlers.
However it is not always correct to raise the thread abort exception. If you are running or about to run code in a finally block then we want to defer
raising the thread abort until we have completed the execution of the finally region.

The older JIT, now known as the legacy JIT, also performed an optimization known as "finally cloning" which also can complicate this decision.

So for the sample test code that you provided the runtime decided not to re-raise the thread abort upon returning from the catch clause.
The thready is tagged with "Thread Abort" so at the next opportunity we will raise thread abort again.
In your test case that is at the Pinvoke into the Sleep, which is inside the try region.

As I mentioned your test case is does execute correctly using our current test binaries for the next version of the Desktop CLR.




Thank you again for you feedback on this.

Microsoft JIT Dev team member.


Posted by Kevin Gosse on 4/5/2017 at 1:17 AM
Thanks for the heads up, but this is a .NET Framework bug, not a VS2017 one. I filled it here because it says "Visual Studio and .NET Framework". Is it the wrong category?
Posted by Microsoft on 4/5/2017 at 12:09 AM
Hello! Now we have built a better report a problem site(https://developercommunity.visualstudio.com/index.html) for VS2017 bugs,please launch VS2017 and sign in, then report the problem using the VS IDE in-product Report-a-Problem tool to us by right-clicking on the feedback icon next to QuickLaunch, or by choosing Help | Send Feedback | Report a Problem from the main menu if you encounter a problem with Visual Studio in the future.
For more information, see details from https://docs.microsoft.com/en-us/visualstudio/ide/how-to-report-a-problem-with-visual-studio-2017.
Posted by Microsoft on 4/4/2017 at 6:14 PM
Thank you for your feedback, we are currently reviewing the issue you have submitted.

Microsoft Visual Studio Connect Support Team