Bug 32508 - Inconsistent handling of AppDomain.CurrentDomain.UnhandledException
Summary: Inconsistent handling of AppDomain.CurrentDomain.UnhandledException
Status: NEW
Alias: None
Product: Runtime
Classification: Mono
Component: JIT (show other bugs)
Version: 4.0.0
Hardware: PC Windows
: --- normal
Target Milestone: ---
Assignee: Zoltan Varga
URL:
: 37547 (view as bug list)
Depends on:
Blocks:
 
Reported: 2015-07-27 18:22 UTC by Alex Lennon
Modified: 2016-01-25 11:05 UTC (History)
5 users (show)

See Also:
Tags:
Is this bug a regression?: ---
Last known good build:


Attachments
Test case (1.17 KB, text/plain)
2015-07-27 18:22 UTC, Alex Lennon
Details

Description Alex Lennon 2015-07-27 18:22:01 UTC
Created attachment 12244 [details]
Test case

[I am not sure if this is best placed in Class libraries/corlib or in Runtime/?]

When an exception results in a call to an UnhandledException handler, and another exception then occurs but should be caught within the code-path in that handler, the exception appears not to be caught correctly.

I have attached a test case based on mono/tests/threadpool-exception5.cs which exhibits similar behaviour triggered when LC_ALL=C.

Running this test case under:

(1) .NET results in the application displaying the following and exiting correctly from handler

Main thread sleeping
Entering OnUnhandledException
Exception was thrown and caught in OnUnhandledException
OnUnhandledException Exiting

(2) Mono/Windows v4.0.1 results in the following message displaying. The following code in OnUnhandledException does not exit and instead the main thread eventually exits

Main thread sleeping
Entering OnUnhandledException
Exception was thrown and caught in OnUnhandledException
exception inside UnhandledException handler: Thread was being aborted
Main thread exiting

(3) Mono/Linux v4.0.3.19 Ubuntu x64 14.02.2

Main thread sleeping
Entering OnUnhandledException
Exception was thrown and caught in OnUnhandledException
exception inside UnhandledException handler: Thread was being aborted
Main thread exiting

...

The issue appears to be that although the exception in OnUnhandledException is caught the Mono runtime is treating it as though it is not caught/partially caught.
Comment 1 Zoltan Varga 2015-08-03 16:37:32 UTC
The unhandled exception is actually the ThreadAbort exception which is thrown by Thread.CurrentThread.Abort(); in the testcase.
Comment 2 Alex Lennon 2015-08-04 05:38:59 UTC
I don't  believe that's correct. OnUnhandledException() is called as a result of that original Abort(). The second exception causes the message, although it should be caught within OnUnhandledException90. 

The behaviour is most definitely different between .NET and Mono here..
Comment 3 Zoltan Varga 2015-08-04 12:48:58 UTC
ThreadAbortExceptions are rethrown at the end of each catch clause, maybe this shouldn't be done in OnUnhandledException().
Comment 4 Alex Lennon 2015-08-04 12:57:32 UTC
Zoltan,

OK, I may be misunderstanding here but I think there is slightly more to it.

Revisiting the test case I provided, if I change the try { } catch block to remove the throwing of Exception() then all works.

        try
        {
            Console.WriteLine("In try catch block");
     //       throw new Exception();
        } catch(Exception ex)
        {
            Console.WriteLine("Exception was thrown and caught in OnUnhandledException");
        }

i.e. the original ThreadAbortException is not causing a problem when no new Exception is thrown. 

If a new Exception is thrown and that is causing the ThreadAbortException to be rethrown also then I would agree that that probably shoouldn't be happening in the un-handled exception handler (?)
Comment 5 Alex Lennon 2015-08-04 13:05:04 UTC
I see what you mean. Modifying the test case as follows is successful

    try
        {
            try
            {
                throw new Exception();
            }
            catch (Exception ex)
            {
                Console.WriteLine("Exception was thrown and caught in OnUnhandledException");
            }
        }
       catch (ThreadAbortException)
        {

        }
        
Yes, it seems to me that the unhandled exception that causes the unhandled exception handler to execute shouldn't still be hanging around waiting to cause problems if another exception occurs.
Comment 6 Ludovic Henry 2015-10-01 10:59:40 UTC
This is an issue with the way ThreadAbortException are rethrown. Here is a simpler case that do not use the ThreadPool or anything fancy:

using System;
using System.Threading;

class Driver
{
	static void Main ()
	{
		try {
			Console.WriteLine ("Before Abort");
			Thread.CurrentThread.Abort ();
		} catch (Exception) {
			try {
				Console.WriteLine ("Before Exception");
				throw new Exception ("Inner");
			} catch (Exception e) {
				Console.WriteLine ("Catch '{0}'", e.Message);
			}

			Console.WriteLine ("ThreadAbortException has not been rethrown");
		}
	}
}

(1) .NET results :

Before Abort
Before Exception
Catch 'Inner'
ThreadAbortException has not been rethrown

(2) Mono result :

Before Abort
Before Exception
Catch 'Inner'

That has to do with the way we rethrow ThreadAbortException at the end of a catch clause.
Comment 7 Ludovic Henry 2016-01-25 11:05:23 UTC
*** Bug 37547 has been marked as a duplicate of this bug. ***

Note You need to log in before you can comment on or make changes to this bug.