Le 的个人资料Something like a home pa...照片日志列表更多 工具 帮助
10月11日

如何查看一个listening socket的accept queue已满?

各位已经知道的不要笑话俺。这个惊天大秘密终于被我发现了,考!

看一看 Documentation/networking/proc_net_tcp.txt

   00000150:00000000 01:00000019 00000000
      |        |     |     |       |--> number of unrecovered RTO timeouts
      |        |     |     |----------> number of jiffies until timer expires
      |        |     |----------------> timer_active (see below)
      |        |----------------------> receive-queue
      |-------------------------------> transmit-queue

这个receive-queue就是:sk->sk_ack_backlog

具体的代码在:http://lxr.linux.no/#linux+v2.6.31/net/ipv4/tcp_ipv4.c#L2236

于是我终于大概明白了为什么我的gentoo-cn.org过一段时间就会连接不上……

且看gentoo-cn.org上现在的80端口的sk_ack_backlog大小:
$ cat /proc/net/tcp | grep 00:0050
   5: 00000000:0050 00000000:0000 0A 00000000:00000081 02:0000000A 00000000     0        0 11883408 2 980000003eb4ad00 300 0 0 2 -1                 

注意粗体部分:0x81,就是129!正好大于128!!!

128是什么?128就是 /proc/sys/net/core/somaxconn, so max connections, 默认的accept q大小!!!

所以内核就会认为acceptq满了!!!http://lxr.linux.no/#linux+v2.6.31/include/net/sock.h#L539

所以后续连接最多只能处于SYN_RECV状态,而永远不会再有连接转成ESTABLISHED状态!!!

不过问题还没最终解决。因为目前我不能理解的是,为什么有129这么高。而且如果说是因为没有accept(),那服务器端也没有CLOSE_WAIT状态的连接。

啊!!!

PS:发现apache配置中MaxClient为150,而目前有150个线程疑似处于死锁状态:
#0  0x2acd4144 in __lll_lock_wait () from /lib/libpthread.so.0
#1  0x2accfbb8 in pthread_cond_destroy@@GLIBC_2.3.2 () from /lib/libpthread.so.0
#2  0x2bae081c in my_thread_end () from /usr/lib/libmysqlclient_r.so.15
#3  0x2b5b4808 in zm_deactivate_mysql () from /usr/lib/apache2/modules/libphp5.so
#4  0x2b6f48a8 in module_registry_cleanup () from /usr/lib/apache2/modules/libphp5.so
#5  0x2b6ffedc in zend_hash_reverse_apply () from /usr/lib/apache2/modules/libphp5.so
#6  0x2b6f1e60 in zend_deactivate_modules () from /usr/lib/apache2/modules/libphp5.so
#7  0x2b693d00 in php_request_shutdown () from /usr/lib/apache2/modules/libphp5.so
#8  0x2b78aa84 in ?? () from /usr/lib/apache2/modules/libphp5.so

案情渐渐明朗……

PPS: 果然,杀掉其中一个进程(含27个线程,其中有25个死锁),就可以访问了。
我猜测apache在select()返回后,先创建线程,然后在线程中accept()。
但是现在线程总数的限制已经达到。所以无法创建新线程来accept()。
同时由于某目前尚未了解到的原因,原来的ESTABLISHED状态的连接也没了。

为解决这个问题,眼下之计,要加入debug信息重新emerge apache。
好在我有debugemerge脚本,哼哼。
然后在下次问题再重现时,再分析为何死锁。
不能学hw,明明缺少信息,还白耗时间在上面,硬要找出原因。

评论

请稍候...
很抱歉,您输入的评论太长。请缩短您的评论。
您没有输入任何内容,请重试。
很抱歉,我们当前无法添加您的评论。请稍后重试。
若要添加评论,需要您的家长授予您相应权限。请求权限
您的家长禁用了评论功能。
很抱歉,我们当前无法删除您的评论。请稍后重试。
您已超过了一天之内允许提供的评论数上限。请在 24 小时后重试。
因为我们的系统表明您可能在向其他用户提供垃圾评论,您的帐户已禁用了评论功能。如果您认为我们错误地禁用了您的帐户,请联系 Windows Live 支持部门
完成下面的安全检查,您提供评论的过程才能完成。
您在安全检查中键入的字符必须与图片或音频中的字符一致。

若要添加评论,请使用您的 Windows Live ID 登录(如果您使用过 Hotmail、Messenger 或 Xbox LIVE,您就拥有 Windows Live ID)。登录


还没有 Windows Live ID 吗?请注册

引用通告

此日志的引用通告 URL 是:
http://zhllg.spaces.live.com/blog/cns!956A48A2D7ED7265!3936.trak
引用此项的网络日志