Open zahirtezcan opened 3 years ago
Top-level statements don't do anything special regarding exceptions. All they do is wrapping your code inside a class inside a method that is marked as the main method of the program.
Though I don't know anything about the behavior you're describing. As far as I can tell, finally
blocks work just fine on the main thread in .Net Core.
finally
blocks run if stack-unwinding occurs. And, for runtime it is optional to implement stack unwinding in absence of root catch
statement.
Here is my quick tests on different online compilers, one of them is .NET 5 other is dotnet v2:
https://dotnetfiddle.net/PQqZO6 https://replit.com/@zahirtezcanbugs/NoCatchFinally
EDIT: It can be beneficient to provide code here as well
using System;
public class Program
{
public static void Main()
{
try
{
AppDomain.CurrentDomain.UnhandledException += (sender, e) => Console.WriteLine("UNCAUGHT " + (e.IsTerminating ? "TERMINATING" : ""));
throw new Exception("GO");
}
//uncomment following line for finally to work
//catch{}
finally
{
Console.WriteLine("FINALLY");
}
}
}
Interesting, though I only see this behavior on Linux, not on Windows. And yes, it's the same with top-level statements.
This code:
using System;
try
{
AppDomain.CurrentDomain.UnhandledException += (sender, e) => Console.WriteLine("UNCAUGHT " + (e.IsTerminating ? "TERMINATING" : ""));
throw new Exception("GO");
}
finally
{
Console.WriteLine("FINALLY");
}
Produces:
> dotnet run
UNCAUGHT TERMINATING
Unhandled exception. System.Exception: GO
at <Program>$.<Main>$(String[] args) in C:\code\tmp\hwapp\Program.cs:line 6
FINALLY
> wsl dotnet run
UNCAUGHT TERMINATING
Unhandled exception. System.Exception: GO
at $Program.$Main(String[] args) in /mnt/c/code/tmp/hwapp/Program.cs:line 6
>
This behaviour is default for the C++ compilers that I know of (MSVC, GCC, clang) unless you specify as a compiler flag. That is, for any thread I tend to put a root try-catch block to make RAII to work efficiently. Similarly, since unwinding and finally does not work, using
statements do not work either.
So, interprocess communication or stateful service communication (some OS resources?) may not be shutdown gracefully and the documentation should reflect this accordingly.
Thanks for this discussion. As @svick points out, top level statements don't change the already defined behavior. That's worth stating in this article.
With .NET Core and also .NET 5 runtime, the default for stack-rewind on the main thread is, when the exception occurs the runtime does not rewind and your application crashes. Only thing you may get is an event trigger for uncaught exceptions from
AppDomain
.What is the default exception handling for Top-level statements? Does it inject a
try-catch
block, so the stack unwinding occurs and we get our finally blocks working? Or, does it ignore everything about exception handling?Document Details
⚠ Do not edit this section. It is required for docs.microsoft.com ➟ GitHub issue linking.
Associated WorkItem - 345704