最近知りました。

詳細については、以下を参考ください。

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

以上

コメントがあればどうぞ


CAPTCHA Image
Reload Image