【问题标题】:.NET 4.5: internal error in the .NET Runtime (80131506) / disabling concurrent GC.NET 4.5:.NET 运行时内部错误 (80131506) / 禁用并发 GC
【发布时间】:2013-10-09 20:17:59
【问题描述】:

我有一个长期运行的 .NET 4.5 应用程序随机崩溃,并在事件日志中留下我在问题标题中提到的消息。该问题在 3 台不同的机器和 2 个不同的系统(2008 R2 和 2012)上重现。应用程序不使用任何不安全/非托管的组件,它是纯托管的 .NET,唯一非托管的东西是 CLR 本身。

这是我从转储中提取的崩溃站点的堆栈跟踪:

clr.dll!MethodTable::GetCanonicalMethodTable()  
clr.dll!SVR::CFinalize::ScanForFinalization()  - 0x1a31b bytes  
clr.dll!SVR::gc_heap::mark_phase()  + 0x328 bytes   
clr.dll!SVR::gc_heap::gc1()  + 0x95 bytes   
clr.dll!SVR::gc_heap::garbage_collect()  + 0x16e bytes  
clr.dll!SVR::gc_heap::gc_thread_function()  + 0x3e bytes    
clr.dll!SVR::gc_heap::gc_thread_stub()  + 0x77 bytes    
kernel32.dll!BaseThreadInitThunk()  + 0x1a bytes    
ntdll.dll!RtlUserThreadStart()  + 0x21 bytes    

此问题与here 讨论的问题非常相似,因此我尝试了该主题中建议的解决方案,但均无济于事:

  • 我已经尝试安装 this 修补程序,但它不会安装在我的任何计算机上(KB2640103 不适用,或者被您计算机上的其他条件阻止),这实际上是有道理的,因为我使用的是 4.5,而不是 4.0。

  • 我已尝试禁用并发 GC 和/或启用服务器 GC。现在我的 app.config 的相关部分如下所示:

    <?xml version="1.0"?>
    <configuration>        
        <runtime>
            <gcConcurrent enabled="false"/>
            <gcServer enabled="true" />
        </runtime>
    <startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>    </startup></configuration>
    

虽然奇怪的是我仍然在进程转储中找到多个与 GC 相关的线程。除了发生崩溃的线程之外,还有 7 个线程具有以下堆栈跟踪:

ntdll.dll!NtWaitForSingleObject()  + 0xa bytes  
KERNELBASE.dll!WaitForSingleObjectEx()  + 0x9a bytes    
clr.dll!CLREventBase::WaitEx()  + 0x13f bytes   
clr.dll!CLREventBase::WaitEx()  + 0xf7 bytes    
clr.dll!CLREventBase::WaitEx()  + 0x78 bytes    
clr.dll!SVR::t_join::join()  + 0xd8 bytes   
clr.dll!SVR::gc_heap::scan_dependent_handles()  + 0x65 bytes    
clr.dll!SVR::gc_heap::mark_phase()  + 0x347 bytes   
clr.dll!SVR::gc_heap::gc1()  + 0x95 bytes   
clr.dll!SVR::gc_heap::garbage_collect()  + 0x16e bytes  
clr.dll!SVR::gc_heap::gc_thread_function()  + 0x3e bytes    
clr.dll!SVR::gc_heap::gc_thread_stub()  + 0x77 bytes    
kernel32.dll!BaseThreadInitThunk()  + 0x1a bytes    
ntdll.dll!RtlUserThreadStart()  + 0x21 bytes    

这让我想知道我是否可以以某种方式搞砸禁用并发 GC(这就是我实际列出的配置)。

我想这就是我迄今为止设法找到的内容。对于如何继续处理这个问题,我真的可以使用一些帮助。

【问题讨论】:

  • GC堆上托管对象的对象头损坏,找不到该类型的方法表。您总是首先寻找与您互操作的非托管代码以寻找原因。修改 gc 配置并不能解决问题。
  • 终结器可能有问题?您可以尝试在终结器中设置断点或将其注释掉。
  • scan_dependent_handles:最近将依赖句柄添加到 CLR(4.0?)。也许这是 CLR 中的真正错误。
  • @HellBrickAK,你找到解决方案了吗?我遇到了一个非常相似的问题。
  • 很遗憾没有。我没有足够的时间进一步调查这个问题,所以我不得不恢复负责它的功能。我最近从头开始重新实现它,到目前为止它似乎工作正常,但我仍然无法理解我在第一次尝试时做错了什么。

标签: c# .net garbage-collection clr .net-4.5


【解决方案1】:

我借鉴了我过去在我们的应用程序中的经验。如果异常在 Finalizer 级别之前未处理,则可能会导致这种情况,如果它继续......它将使应用程序崩溃。

在对 GC 配置进行任何操作之前..

快速检查... 您是否使用任务并行库?。 如果是,请确保您正确处理异常。如果来自不同线程的异常没有得到处理,它将进入 Finalizer,然后使应用程序崩溃。有几种方法可以巧妙地处理它们。处理“聚合”异常是一种方法(我们曾经解决过!)。

http://msdn.microsoft.com/en-us/library/dd537614.aspx

我没有 50 分来添加评论,所以将其添加为答案...

【讨论】:

  • 在我启用了一个非常积极地使用 TPL 的组件后,问题确实开始出现,但我认为未处理的异常在这里没有错。原因是: 1. 对任务执行的所有回调都包装在 try-catch 块中; 2.我已经订阅了AppDomain.Current.UnhandledException,并且AFAIR它是在这个任务异常+终结器案例中触发的; 3. 我看不出它怎么可能破坏托管堆,这似乎就是这里发生的事情。
  • 1) 你是说 AppDomain.Current.UnhandledException 被触发了吗?这意味着有些事情没有处理,在这里记录并获取更多数据。 2) Finalizer 的异常是致命的。 3)在你的转储分析'!threads'并检查终结器线程和!pe你应该看到异常。如果是这样的话:)..让我知道..
  • 我的意思是我有一个 AppDomain.Current.UnhandledException 处理程序,但它没有在我的应用程序中触发,即使它应该是一个简单的终结器异常(我刚刚仔细检查过这是通过以下测试应用程序:http://pastebin.com/9EgzBZQA)。或者未处理的任务异常是否以其他方式传播,不包括从终结器中抛出它们?关于转储探索建议:我稍后会尝试,首先我需要研究一下你所说的它们是什么意思=)(这整个转储对我来说有点新鲜)
  • 如果您未能检查任务的 Result 属性,也可能会出现未处理的异常。不要忘记您还必须在TaskScheduler.UnobservedTaskException 上附加一些内容以避免进程崩溃。我们只是通过处理后者才发现关于前者的。
【解决方案2】:

我意识到这是一篇旧帖子,但是,我遇到了与 OP 相同的问题。 atlaste 提出的观点:

将运行时更改为 x86 或 x64 并重试;你也可以像你已经尝试过的那样弄乱并发 GC 设置。

对我来说是关键。我的所有项目都设置为 Any CPU 除了一个(巧合的是应用程序的入口点,它是一个控制台应用程序项目)。该项目设置为 x86。一旦我将其更改为 Any CPU,应用程序就会正常运行。

【讨论】:

    【解决方案3】:

    对我有帮助的解决方案:卸载 .NET 4.5.1,安装 4.0,安装提到的修补程序,重新安装 4.5.1。

    【讨论】:

      【解决方案4】:

      我刚刚完成了与 Microsoft 的对话,因为我能够重现类似的问题。

      在我的情况下,这是 .NET 运行时中的一个错误,它与混合动态类型和非动态代码有关。我不确定您的情况是否也是这种情况,但您可能想尝试一些事情:

      • 在 Windows 8.1 上运行代码(最新更新)。显然,Windows 8.1 的 .NET 版本比其他版本的 Windows 更新。
      • 如果您使用 AssemblyBuilder(像我一样),请尝试将其更改为 Run 模式而不是 RunAndCollect
      • 将运行时更改为 x86 或 x64 并重试;你也可以像你已经尝试过的那样弄乱并发 GC 设置。
      • 正如我们所说,我的错误正在修复,这基本上意味着将有一个 Windows 更新来处理它。也许只是等待它也是一种选择;我预计这不会花费太长时间,因为这对很多程序来说都非常重要。

      【讨论】:

        【解决方案5】:

        我终于找到了可以安装的修复程序。我也有 4.5 并且没有安装 4.0 的其他修复程序。删除 4.5 也没有修复它。 Fix in 链接其实已经修复了。

        http://kb.machsol.com/Knowledgebase/Article/50305

        【讨论】:

          【解决方案6】:

          我们的 .NET 4.5 桌面应用程序 - 网络爬虫也遇到了同样的问题。它在重载下随机坠毁。所以几个月来我们一直在寻找找出原因的方法:我们已经尝试了所有方法!禁用并发 GC,将其设置为服务器模式和许多其他解决方法,直到我们意识到由于 PhantomJS 模块而发生崩溃。它使用了一些非托管资源并且之后不会清除它们 :( 所以我们为 PhantomJS 集成创建了一个独立的控制台应用程序。现在我们使用来自网络爬虫的Process.Start 执行这个控制台应用程序,然后将其杀死。它需要有更多时间进行抓取,但不会再出现崩溃!

          【讨论】:

            【解决方案7】:

            我的问题是每 5-10 分钟我的应用程序池就会因退出代码 (80131506) 而崩溃。我不确定在高线程操作/计划任务中是否应该推垃圾收集器,但以下解决方案适用于此。

            我添加了一个每分钟调用 GC.GetTotalMemory(true) 的作业。我假设,出于某种原因,GC 不会自动调用垃圾收集器,因为我使用的大量一次性对象不够频繁。但这解决了我的问题!这更像是一个快速修复而不是最终解决方案;)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-06-21
              • 1970-01-01
              • 1970-01-01
              • 2011-05-21
              • 1970-01-01
              相关资源
              最近更新 更多