【问题标题】:Gracefully handling corrupted state exceptions in .NET Core优雅地处理 .NET Core 中的损坏状态异常
【发布时间】:2018-02-08 09:56:03
【问题描述】:

我基本上有一个重复的 question,但对于 .NET Core。

我有核心控制台应用程序:

class Program
{
    static void DoSomeAccessViolation()
    {
        // if you have any questions about why this throws,
        // the answer is "42", of course

        var ptr = new IntPtr(42);
        Marshal.StructureToPtr(42, ptr, true);
    }

    [SecurityCritical]
    [HandleProcessCorruptedStateExceptions]
    static void Main(string[] args)
    {
        try
        {
            DoSomeAccessViolation();
        }
        catch (Exception ex)
        {
            Console.Error.WriteLine(ex);
        }
    }
}

我已尝试添加 Settings.setting 文件

<SettingsFile xmlns="http://schemas.microsoft.com/VisualStudio/2004/01/settings" CurrentProfile="(Default)" GeneratedClassNamespace="ConsoleApp2" GeneratedClassName="Settings1">
  <Profiles />
  <Settings>
    <Setting Name="legacyCorruptedStateExceptionsPolicy" Type="System.Boolean" Scope="Application">
      <Value Profile="(Default)">True</Value>
    </Setting>
  </Settings>
</SettingsFile>

我已经尝试根据docs设置环境变量:

C:\>set COMPlus_legacyCorruptedStateExceptionsPolicy=1
C:\>dotnet run

C:\>set COMPlus_legacyCorruptedStateExceptionsPolicy=true
C:\>dotnet run

(在 Windows 上)。但是没有任何效果,应用程序总是在不打印异常的情况下严重崩溃。

【问题讨论】:

  • 它不会因 AVE 而崩溃。您无法收取费用。除了 CoreCLR 中的错​​误之外,很难将其称为任何错误,请考虑提交错误报告。
  • @JanHudecek 你有没有为此提交过错误?

标签: c# .net-core access-violation corrupted-state-exception


【解决方案1】:

我一直在研究这个主题的一些背景,按时间顺序排列...

dotnet/coreclr Issue #9045:剥离损坏状态异常处理

dotnet/coreclr PR #10957:不尊重属性 HandleProcessCorruptedStateExceptions

dotnet/coreclr Issue #19192:无法在托管代码中捕获从本机 Linux 代码引发的任何用户异常

我目前是 SOL。 必须创建各种非托管包装器来捕获外部 CSE。

您可以尝试few more options,特别是结合 legacyCorruptedStateExceptionsPolicy 的 FailFastOnCorruptedStateException。

【讨论】:

    【解决方案2】:

    我运行了您的代码,引发的异常是 ExecutionEngineException。这是运行时中的致命错误,意味着运行时无法进一步执行您的程序。您无法捕获此异常是有充分理由的:您无法处理它。您的代码无法“修复”运行时并继续运行。

    来自 Microsoft 文档:公共语言运行时的执行引擎中出现内部错误时引发的异常。 并且:此类型之前表示运行时中存在未指定的致命错误。运行时不再引发此异常,因此此类型已过时。

    【讨论】:

    • 我实际上不是为了这个特定的崩溃而调查它——我在 Web 服务器中使用了一个本机库(有一个失败的断言)。它每周发生一次,因此很难调试以查看确切的异常。打印异常会很好,看看是什么请求导致它并退出而不是 FailFast 并在 syslog 中使用一行
    • “修复”或从严重崩溃中“恢复”并不是唯一的用例。打印出一些有用的细节可能会成功,并且会加快此类崩溃的调试时间。我实际上是在 .Net Framework 中做类似的事情,现在正在寻找在 dotnet core 中做的事情。
    【解决方案3】:

    .net 核心中唯一保留的就是legacyCorruptedStateExceptionsPolicy 行为。

    要启用此功能,您必须在进程启动之前将COMPlus_legacyCorruptedStateExceptionsPolicy 环境变量设置为1。 但是,在 .net 核心中,由于在 .net 移植期间做出的决定,它捕获的损坏状态异常远少于 .net 中的:(

    例如,如果您将代码中的Marshal.StructureToPtr(42, (IntPtr)42, true); 替换为Marshal.ReadInt32((IntPtr)42);(并设置环境变量)将成功生成并捕获AVE。

    您可以阅读有关此问题的详细信息here

    关于 .net 核心中损坏状态异常的总体情况:

    1. 要捕获其中一些,请在进程开始之前将 COMPlus_legacyCorruptedStateExceptionsPolicy 环境变量设置为 1
    2. 如果您从本地调用获得 CSE。尝试将异常处理移到那里(如果您有源代码),或者尝试将非托管包装器作为 TylerY86 suggested
    3. 编写 WatchDog 进程来检查您的应用程序崩溃(如果这很重要)。 然后查看事件日志并分析故障转储...

    【讨论】:

      猜你喜欢
      • 2017-02-18
      • 1970-01-01
      • 2012-02-16
      • 1970-01-01
      • 1970-01-01
      • 2017-03-04
      • 2014-07-10
      • 1970-01-01
      • 2016-07-30
      相关资源
      最近更新 更多