4

我在一个经典的 ASP Web 应用程序上工作,它使用了几个用 VB6 编写的旧 COM 组件。所有 VB6 组件都在 COM+ 应用程序中注册,这些应用程序在它们自己的 dllhost 进程中运行。大部分应用程序已转换为 .Net,但仍有许多遗留页面和组件。COM Interop 用于两个方向,从经典的 ASP 和 VB6 调用一些 .Net 程序集以及从 ASP.Net 调用 VB6 组件。该应用程序以经典管道模式在 Windows Server 2008 R2 (IIS 7.5) 上运行。

在大多数情况下,该应用程序运行良好。最终放弃了向 .Net 的过渡,取而代之的是开发了一种新产品。同时,旧产品必须保持其异构状态。

我无法跟踪 Web 应用程序挂起的间歇性问题。用户在浏览器等待时只会看到一个空白屏幕,而服务器从不响应。挂起一直存在,直到我手动终止托管 VB6 组件的 dllhost 进程,所以我相信问题就在那里。可能是内存泄漏或失控的循环循环。

系统每天有成千上万的用户,但问题每周只发生一到两次。幸运的是,我们有一个网络农场,它会在服务器停止响应时自动将其拉出,因此对客户的影响为零。不过,我想弄清楚发生了什么。

我重新编译了所有 VB6 组件以包含调试符号并重新部署到生产环境中。当问题发生时,我使用 32 位任务管理器 (c:\windows\syswow64\taskmgr.exe) 对 dllhost 进程进行故障转储。我最终得到了一个 dllhost.dmp 文件,我将它带到我的开发工作站并在 VS2010 中打开。我有 VB6 在我的符号路径中创建的 .pdb 符号文件。当我在 VS2010 中启动调试会话时,我可以转到 Modules 屏幕并看到确实加载了我的组件的所有符号。

然后去哪儿?调用堆栈没有显示我自己的任何组件。它看起来像这样:

调用堆栈

调用堆栈顶部的反汇编如下所示:

拆卸

不知道我还能做什么。我检查了调用堆栈的每一帧的所有本地人,这对我来说是胡言乱语。我没有看到对我自己的任何组件的任何引用。

也许 WinDbg 会产生更多信息?不知道从哪里开始。

我很确定,如果我能在挂起发生时找到正在调用的 VB6 类/方法,我就能深入了解它。我尝试添加一些日志记录,但结果不一致。

也许我的 VB6 组件完全没有问题,但我遇到了 Windows 或 IIS 中的一些错误?

任何建议都将不胜感激,但目前不能选择放弃 VB6。谢谢。

4

1 回答 1

1

不是一个完整的答案,但CoRegisterSurrogateEx被记录为只要代理进程正在运行就阻塞:

CoRegisterSurrogateEx 函数是一个阻塞函数。在 COM+ 确定进程将被关闭之前,它不会返回。在调用此函数之前,将此线程上的 COM 初始化为多线程单元 (MTA)。

所以我认为错误不在这个调用堆栈上。(您可以看到它在 WaitForSingleObject 调用上仍然阻塞,很可能是它用来阻塞直到进程关闭的机制)。

于 2012-08-29T21:46:14.993 回答