godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
91.14k stars 21.19k forks source link

Mono No errors reported for async functions, game continues #25015

Open ghost opened 5 years ago

ghost commented 5 years ago

Godot version:

c6b587636b1e3cf27e566e6e5b10859316cbefb6

OS/device including version:

Ubuntu 18.10, Mono 5.16

Issue description:

When an async function fails to execute due to an error, it will not report the error to the console, and will not stop execution of the game.

Steps to reproduce: Do something erroneous in an async function; observe that your mistake is not reported.

using Godot;
using System.Threading.Tasks;

public class TestScript : Node
{
    public override void _Ready()
    {
        AsyncFunc();
    }

    private async Task AsyncFunc()
    {
        GD.Print("Running...");
        var myArray = new int[3];
        myArray[4] = 0; //Whoopsie-doodle!
        GD.Print("Done.");
    }
}

Minimal reproduction project:

NoAsyncError.zip

NathanWarden commented 5 years ago

I just tried running your code in MonoDevelop in a .Net Console app and it seems this is expected behavior since your error occurs in an async method.

If you want to catch the exception you need to assign the task when calling AsyncFunc and then check once task.IsCompleted is true whether or not task.Exception is null or not. If it isn't null then the async method threw an exception.

Edit: Actually you could probably check task.IsCompletedSuccessfully for whether it threw an exception or not.

static void Main(string[] args)
{
    Task task = AsyncFunc();

    // Blocking here for testing purposes
    while (!task.IsCompleted) {}

    if (task.Exception != null)
    {
        // You could re-throw the exception here, but I'm just printing the exception message
        Console.WriteLine(task.Exception.Message);
    }
}

static async Task AsyncFunc()
{
    Console.WriteLine("Running...");
    var myArray = new int[3];
    myArray[4] = 0; //Whoopsie-doodle!
    Console.WriteLine("Done.");
}
ghost commented 5 years ago

@NathanWarden thanks for investigating; I figured it might be something inherent to C#. @neikeq wanted an issue opened for it, in any case. I wound up working with the following code to get errors to show up in the editor:

try {
    await AsyncFunc();
} catch (System.Exception e) {
    GD.Print(e.Message);
}
shartte commented 5 years ago

I think this is inherent to the Task library. You're not actually waiting for the Task so there's no place the exception would actually be reported. If you change your example code in this way: AsyncFunc().Wait() Then it'll actually report the underlying exception.