如何调试一个ASP.NET进程内存转储文件?

4
抱歉,我无法想出一个好的方式来表达我的真正问题。
我在一台64位机器上运行一个高流量的ASP.NET站点。由于应用程序中的一些旧组件,我正在以32位模式运行IIS。我将此特定的Web应用程序运行在启用Web Garden选项的应用程序池内(在8核机器上运行6个进程)。
每周一两次,其中一个进程会飙升到100%的CPU利用率,导致网站大幅减速,因此我的计划是等待发生这种情况,内存转储有问题的进程,然后使用WinDbg查找导致线程飙升的原因,以确定代码出现了什么问题。
我以前使用WinDbg进行过调试,以找出网站上发生死锁的原因,但那是几个月前的事情,我记不得如何使其工作了。(顺便说一句,这是一个记录你所做的一切的教训。)
我在运行站点的Windows 2003服务器上运行WinDbg,以防止任何DLL版本问题。到目前为止,我的步骤如下,请告诉我我在哪里出错了,以获得我收到的错误消息。
1.首先使用UserDump内存转储尖峰进程,使用以下命令,其中3389是进程的ID: userdump -k 3389
2.将转储加载到x86版WinDbg中。
3.由于我在64位机器上运行32位,因此我首先加载内存转储,然后: .load wow64exts .effmach x86
4.确保我的符号路径包括包含我的应用程序PDB文件的目录: .sympath+ c:\inetpub\myapp\bin
5.“仅加载SOS”失败,并显示“系统找不到指定的文件”的错误,因此我采用以下完全限定路线,它可以正常工作: .load c:\windows\microsoft.net\framework\v2.0.50727\sos
从这里开始,我迷失了。 我尝试任何SOS命令,例如!threads,只会得到此错误:
Failed to load data access DLL, 0x80004005

那个错误还伴随着一系列我应该验证的项目编号列表。我已经验证了我正在运行最新版本的调试器,mscordacwks.dll文件确实与mscorwks.dll文件在同一个目录中,并且我正在与转储文件相同的体系结构上进行调试。
我也运行了神奇的“.cordll -ve -u -l”命令,但那并没有解决任何问题。当我执行它时,总是会收到“CLR DLL status: No load attempts”的提示。然后我尝试“.reload”,这会产生一些警告,如“WARNING: wldap32 overlaps dnsapi”。我希望它说的像“CLRDLL: Loaded DLL C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\mscordacwks.dll”这样,但它没有。

您所描述的症状听起来像是GC2收集。 - Mitch Wheat
你看过Tess的博客了吗?那里有很多有价值的信息。 - Mitch Wheat
5个回答

3

在运行sos命令之前,请尝试执行!sw。请参阅此博客文章


2
我认为!sw只是在32位和64位模式之间切换,这本质上与.effmach x86相同。无论如何我都尝试了,但并没有帮助。谢谢你给我尝试的机会。 - Ken Randall


2

1

我刚刚也遇到了类似的问题。在我的情况下,WinDbg无法找到正确版本的mscorwks.dll。除了框架版本外,还有一个DLL的修订版本,这个版本在同一框架版本之间可能是不同的。

理论上,Microsoft符号服务器应该能够提供必要的DLL,但对我来说并没有发生。为了解决这个问题,我使用了!sym noisy来获取有关符号加载的其他信息。当我执行!dumpstack时,我收到了错误消息:

SYMSRV:http://msdl.microsoft.com/download/symbols/mscorwks.dll/492B82C1590000/mscorwks.dll未找到

为了解决这个问题,我在本地符号缓存中创建了适当的文件夹,并从转储机器上复制了mscorwks.dll。在.reload之后,WinDbg在本地符号缓存中找到了必要的DLL,并继续愉快地进行。

或者,您可以使用lm v m mscorwks查找正在使用的mscorwks的确切版本。然后,您可以从此列表中找到包含所需版本的更新。您需要将必要的DLL从特定更新中提取到正确的位置。


1

伙计 - 不确定这是否有帮助,但或许可以试试这个。

  1. 将 c:\windows\microsoft.net\framework\v2.0.50727\sos.dll 复制到与 windbg 安装在同一目录下的位置(例如 c:\program files\Debugging Tools for Windows\)。为什么?这样可以方便地加载 sos 文件。
  2. 运行 windbg。
  3. 加载内存转储文件。我使用 ctrl-D 或 File -> open crash dump。
  4. .load sos <-- 注意在 load 命令之前有一个句号。
  5. .symfix c:\temp\debug_symbols
  6. .reload

好的...注意命令行。这告诉我转储所在的当前线程。对于高 CPU 场景可能没什么用,因为我们可能在任何线程中。

所以从这里开始,我查看正在运行的线程并检查最繁忙的线程。

8 !threadpool <-- 这是为了查看 CPU 利用率,以检查我们是否处于繁忙状态...例如 100% 的 CPU 等等。

9 !runaway <-- 列出存在时间最长的线程... 例如:

0:027 !runaway
User Mode Time
Thread       Time
18:704       0 days 0:00:17.843   <-- Thread #18
19:9f4       0 days 0:00:13.328   <-- Thread #19
16:1948      0 days 0:00:10.718
26:a7c       0 days 0:00:01.375
24:114       0 days 0:00:01.093
27:d54       0 days 0:00:00.390
28:1b70      0 days 0:00:00.328
0:b7c       0 days 0:00:00.171
25:3f8       0 days 0:00:00.000
23:1968      0 days 0:00:00.000

线程18和19已经挂起了一段时间.. 嗯....它们被卡在循环中了吗?

  1. ~18s <-- 转到线程18。
  2. !clrstack <-- 清除调用堆栈.. 就像在Windows中进行调试一样。

.. 从这里,您可以通过给出地址引用和其他东西来转储对象和其他内容。

查看 !help 列出一些要尝试和使用的命令.. 我认为 !help.sos 也可以工作?

希望对您有所帮助.. 如果您仍然遇到困难,请告诉我们哪些方法有效,哪些方法无效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接