Windows Networking 2: 为什么我的Apache服务停不了。

Windows Networking 2: 为什么我的Apache服务停不了。

这是Windows Networking 排查的第二篇,上次涉及了Windows NDIS的架构以及对该架构下网络问题排查的方法。这次,我们通过一个case,来讲讲NDIS之上,Windows TCPIP 协议栈的实现。

问题

Windows Server 2008 R2 SP1 上,使用Apache部署了服务。当我们尝试停止Apache服务是,该服务一直pending在stopping状态。任何操作都无法恢复,直至重启机器。

方案

在遇到这个问题之前,我们都没有听说过有已知问题会导致Apache服务无法停止,怎么看都是应用的问题。但为避免万一,我们还是经验性的建议,

  1. 卸载不需要的三方软件,尤其是添加了Filter driver或者WFP callout driver的安全软件。
  2. 禁用网卡的高级功能,尤其是TCP Chimney 和 RSS。参考:https://blogs.technet.microsoft.com/onthewire/2014/01/21/tcp-offloadingchimney-rsswhat-is-it-and-should-i-disable-it/
  3. 确认Windows 补丁版本,建议安装最新补丁。

一一尝试之后,确认问题依旧存在。同时我们确认补丁已经升级到最新。至此,我们常规手段已经无法解决问题,只好通过重现问题并抓取Memory dump做进一步分析。

Memory Dump 分析

从Dump来看,我们明确 Apache的服务进程httpd.exe不退出的原因是Afd.sys驱动在等待一个完成信号。

image

由于无法释放afd资源,导致应用程序一直等待,即便强制kill,也会留下zombie进程,只能通过重启解决。

而我们知道,在Windows中AFD资源又是与TCP资源强关联的,只有当对应的TCP资源被释放之后,才会由tcpip.sys调用afd.sys的callback routine,完成释放以及触发信号量的工作。

image

因此,更重要的一个问题是TCP资源为什么没有得到释放。因此,我们直接检查TCP资源的Reference,

image

在Windows系统中,基本上实现了资源的对象管理。对于TCP的一个端口来说,它也是一个对象。对任何对象的操作之前,系统都会尝试AddReference,避免该对象在使用过程中被释放导致Memory Access Violation。在用完该对象之后,系统会调用DeReference的操作,把减少对应的引用计数。一旦当一个对象的Reference count为0,那么它就会被对应的routine释放。对于一个TCP监听端口来说,释放资源就是tcpip!TcpDereferenceListener,例如,

 # Child-SP  RetAddr   Call Site
00 fffff880`05b727b0 fffff880`0160a01e tcpip!TcpDereferenceListener+0xe
01 fffff880`05b727e0 fffff880`0160a039 tcpip!TcpCloseListener+0x6e
02 fffff880`05b72830 fffff880`02b2fa30 tcpip!TcpTlListenerCloseEndpoint+0x9
03 fffff880`05b72860 fffff880`02b2fef2 afd!AfdCleanupCore+0x410
04 fffff880`05b729e0 fffff800`01937aaf afd!AfdDispatch+0x42
05 fffff880`05b72a30 fffff800`01935a2e nt!IopCloseFile+0x11f
06 fffff880`05b72ac0 fffff800`0193565f nt!ObpDecrementHandleCount+0x8e
07 fffff880`05b72b40 fffff800`01935964 nt!ObpCloseHandleTableEntry+0xaf
08 fffff880`05b72bd0 fffff800`016fd9d3 nt!ObpCloseHandle+0x94
09 fffff880`05b72c20 00000000`7774999a nt!KiSystemServiceCopyEnd+0x13

在我们这个问题中,很明显目前这个80端口对应的TCP资源有超过0x36个引用,除开TcpCreateListener,其它的0x35个引用可能是leak,也可能是其他驱动或者软件在操作这个结构所添加的引用。比如说,netstat 在枚举端口信息的时候会增加端口的reference,例如,

image

由于我们明确了系统中没有任何网络相关的三方软件,那么基本上问题就认定为操作系统对于TCP资源的leak。此时,我们基本上就需要跟微软开case,进一步分析操作系统问题。

后记

正当我们准备摩拳擦掌跟微软进一步分析操作系统问题的时候,我们在微软网站上偶尔的发现7月10日发布的最新补丁可能会引发w3svc无法停止的问题,尽管不是Apache,但是问题的描述跟我们发现的本质问题一致,

https://support.microsoft.com/en-us/help/4338818/windows-7-update-kb4338818

image

微软在之后紧急release了新的update 4345459来修复该问题。

https://support.microsoft.com/en-us/help/4345459/stop-error-0xd1-after-a-race-condition-occurs-in-windows-7-service-pac

在我们的这个case中,应用该补丁之后,问题解决。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值