最近知りました。
詳細については、以下を参考ください。
https://github.com/dotnet/runtime/issues/67214
本件ですが、
- WINDOWSは問題なし
- MACはダメ
- LINUXはダメ
ということのようで、LINUXでやってみました。
環境は以下の通りです。
$ cat /etc/os-release
NAME="Pop!_OS"
VERSION="22.04 LTS"
$ dotnet --version
6.0.402
(1. 同期のダメな場合)
public class Program
{
public static void Main(string[] args)
{
try
{
Console.WriteLine("main");
throw new Exception();
}
catch (Exception e)
{
Console.WriteLine("error");
throw; // ←こいつが原因
}
finally
{
Console.WriteLine("finally"); // ここを通過しない
}
}
}
(2. 同期でOKな場合)
public class Program
{
public static void Main(string[] args)
{
try
{
try
{
Console.WriteLine("main");
throw new Exception();
}
catch (Exception e)
{
Console.WriteLine("error");
throw; // ←こいつがいてもfinallyに入る
}
finally
{
Console.WriteLine("finally"); // 上位のエラーハンドラーがいればOK
}
}
catch (Exception e)
{
Console.WriteLine("error - wrapper");
}
}
}
(3. 非同期の場合)
public class Program
{
public static async Task Main(string[] args)
{
try
{
Console.WriteLine("main");
throw new Exception();
}
catch (Exception e)
{
Console.WriteLine("error");
throw; // ←こいつがいてもfinallyに入る
}
finally
{
Console.WriteLine("finally"); // async修飾子があればOK
}
}
}
(4. NET6からの簡易構文の場合)
try
{
Console.WriteLine("main");
throw new Exception();
}
catch (Exception e)
{
Console.WriteLine("error");
throw; // ←こいつがいるとダメ
}
finally
{
Console.WriteLine("finally"); // ここを通過しない
}
以上のように、4つのパターンで試してみました。
asyncの場合は何も気にする必要はないですが、他パターンでは一考が必要かなと。
ちなみに以下のようなエラーになります。
Unhandled exception. System.Exception: Exception of type 'System.Exception' was thrown.
これって、コンテナでやるときにやばいかなと思う。。
気をつけてください。
また、シャットダウンハンドラー(以下のようなコード)を仕込んでみましたが、
動いたのは、「2. 同期でOKな場合」だけでした。
そもそも、asyncはシャットダウンハンドラーって使えない?(要調査)
AppDomain.CurrentDomain.ProcessExit += new EventHandler(ShutdownHander);
public static void ShutdownHander(object sender, EventArgs e)
{
Console.WriteLine("shutdown");
}
(追記)
Unhandled exceptionは、ProcessExitには反応しないようです。
こちらを使う必要があります。
https://learn.microsoft.com/ja-jp/dotnet/api/system.appdomain.unhandledexception?view=net-8.0
以上