This is Xamarin's bug tracking system. For product support, please use the support links listed in your Xamarin Account.
Bug 36560 - Unhandled exceptions outside the main execution context are ignored
Summary: Unhandled exceptions outside the main execution context are ignored
Status: RESOLVED ANSWERED
Alias: None
Product: Runtime
Classification: Mono
Component: General (show other bugs)
Version: unspecified
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: Alex Rønne Petersen
URL:
Depends on:
Blocks:
 
Reported: 2015-12-03 20:49 UTC by Matthew Orlando
Modified: 2017-01-10 11:06 UTC (History)
5 users (show)

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


Attachments

Description Matthew Orlando 2015-12-03 20:49:38 UTC
Unhandled exceptions are supposed to terminate the program. However, if you have an unhandled exception off the main thread, or in a continuation of some async task even on the main thread, the exception will be completely lost. It's not reported in the debug output, it doesn't terminate the app, it just silently fails leading to all manner of confusing behavior.

This happens on all Xamarin platforms (iOS, Android, OSX, Forms) hence my choice of Runtime as the product. 


Reproduce by adding this code pretty much anywhere in the main thread of your app:

Basic thread exception:

    Task.Run(() =>
    {
        throw new Exception("deadbeef");
    });


Continuation exception:

    Task.Run(() =>
    {
        throw new Exception("deadbeef");
    }).ContinueWith(prevTask =>
    {
        if (prevTask.IsFaulted)
        {
            throw prevTask.Exception;
        }
    }, TaskScheduler.FromCurrentSynchronizationContext());


Compare behavior with the same code added to a genuine .Net app (e.g. Windows Forms or WPF)
Comment 1 Matthew Orlando 2015-12-03 21:09:01 UTC
.Net console apps built with Xamarin Studio also lose the exception (only the basic example works; console thread is not a valid synchronization context)
Comment 2 Matthew Orlando 2015-12-03 21:42:59 UTC
On iOS, if I call InvokeOnMainThread inside the continuation instead of using TaskScheduler, the exception propagates as expected.
Comment 3 Matthew Orlando 2015-12-09 19:02:24 UTC
This is making it incredibly frustrating to test new asynchronous code. I add new things that look like they should work, set a breakpoint where I want to check my assumptions, but that breakpoint is never reached, and the app fails silently in ways I may not notice. I basically have to step through every piece of new asynchronous code I add, searching for phantoms.
Comment 4 Aleksey Kliger 2015-12-21 16:52:50 UTC
Matthew, thank you for reporting this issue.

It's not clear to me whether the behavior you describe (exception is not observed on 
the main thread) happens if you call any of the Wait() methods on the created task?  

(Console apps running with Mono and or from the Command Prompt on Windows behave identically here: if the main thread exits before waiting the exception from the task is silently dropped.)
Comment 5 Alex Rønne Petersen 2015-12-22 09:15:01 UTC
Hi,

I believe this is, for better or worse, working as expected. .NET 4.5 changed the default so that unobserved task exceptions don't terminate the process. If you Wait () on the task, you will get the exception as expected.

More details here: http://blogs.msdn.com/b/pfxteam/archive/2011/09/28/task-exception-handling-in-net-4-5.aspx

However, we do not support <ThrowUnobservedTaskExceptions /> at the moment, which is unfortunate as it's the config flag that gives the 'old' behavior. I will have a look at this.
Comment 6 Alex Rønne Petersen 2016-01-13 03:58:57 UTC
I've implemented support for the config element mentioned earlier. A pull request is currently pending review: https://github.com/mono/mono/pull/2424
Comment 7 Matthew Orlando 2016-01-13 17:13:52 UTC
Hi Alexsey & Alex,

Thanks for the clarification. I do see that I was wrong about the way WPF & Windows Forms behave in this respect. It was only in debug builds where it crashed with an unhandled exception. I'm guessing MS enables the ThrowUnobservedTaskExceptions flag for debug builds much like they add bounds checking for STL containers.

I've converted all my code to use await instead of ContinueWith and haven't had any further issues.

Cheers,

Matthew
Comment 8 Matthew Orlando 2016-01-13 17:15:12 UTC
(sorry I spelled your name wrong, Aleksey!)
Comment 9 Alex Rønne Petersen 2016-01-14 02:14:40 UTC
That's entirely possible. I don't think that behavior is documented anywhere, though. I'll investigate at some point.

(BTW, the PR above has been merged, so you can now use this configuration element if you wish.)

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