c – 套接字选择中可能导致死锁的原因

c – 套接字选择中可能导致死锁的原因,第1张

概述我有一个jabber服务器应用程序和C中的另一个jabber客户端应用程序. 当客户端接收并发送大量消息(每秒超过20个)时,这就是select只是冻结而永不返回. 使用netstat,套接字仍然连接在linux和tcpdump上,消息仍然发送到客户端,但select只是永远不会返回. 以下是选择的代码: bool ConnectionTCPBase::dataAvailable( int tim 我有一个jabber服务器应用程序和C中的另一个jabber客户端应用程序.

当客户端接收并发送大量消息(每秒超过20个)时,这就是select只是冻结而永不返回.

使用netstat,套接字仍然连接在linux和tcpdump上,消息仍然发送到客户端,但select只是永远不会返回.

以下是选择的代码:

bool ConnectionTCPBase::dataAvailable( int timeout )  {    if( m_socket < 0 )      return true; // let recv() catch the closed fd    fd_set fds;    struct timeval tv;    FD_ZERO( &fds );    // the following causes a C4127 warning in VC++ Express 2008 and possibly other versions.    // however,the reason for the warning can't be fixed in gloox.    FD_SET( m_socket,&fds );    tv.tv_sec = timeout / 1000000;    tv.tv_usec = timeout % 1000000;    return ( ( select( m_socket + 1,&fds,timeout == -1 ? 0 : &tv ) > 0 )             && FD_ISSET( m_socket,&fds ) != 0 );  }

死锁是与gdb:

Thread 2 (Thread 0x7fe226ac2700 (LWP 10774)):#0  0x00007fe224711ff3 in select () at ../sysdeps/unix/syscall-template.S:82#1  0x00000000004706a9 in gloox::ConnectionTCPBase::dataAvailable (this=0xcaeb60,timeout=<value optimized out>) at connectiontcpbase.cpp:103#2  0x000000000046c4cb in gloox::ConnectionTCPClIEnt::recv (this=0xcaeb60,timeout=10) at connectiontcpclIEnt.cpp:131#3  0x0000000000471476 in gloox::ConnectionTLS::recv (this=0xd1a950,timeout=648813712) at connectiontls.cpp:89#4  0x00000000004324cc in glooxd::C2S::recv (this=0xc5d120,timeout=10) at c2s.cpp:124#5  0x0000000000435ced in glooxd::C2S::run (this=0xc5d120) at c2s.cpp:75#6  0x000000000042d789 in CNetwork::run (this=0xc56df0) at src/Network.cpp:343#7  0x000000000043115f in threading::ThreadManager::threaDWorker (data=0xc56e10) at src/ThreadManager.cpp:15#8  0x00007fe2249bc9ca in start_thread (arg=<value optimized out>) at pthread_create.c:300#9  0x00007fe22471970d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112#10 0x0000000000000000 in ?? ()

你知道吗,即使我们还在发送给他,也会导致选择停止接收消息.
在通过套接字接收和发送大量消息时,linux中是否有缓冲限制?

谢谢

解决方法 有几种可能性.

超过FD_SETSIZE

您的代码正在检查否定文件描述符,但不是超过FD_SETSIZE(通常为1024)的上限.只要发生这种情况,你的代码就是

>破坏自己的堆栈
>向select中显示一个空的fd_set,这将导致挂起

假设您不需要这么多并发打开的文件描述符,解决方案可能包括找到删除文件描述符泄漏,尤其是处理废弃描述符关闭的堆栈代码.

您的代码中存在可疑注释,表明可能存在泄漏:

// let recv() catch the closed fd

如果这个注释意味着有人将m_socket设置为-1并希望recv将捕获已关闭的套接字并关闭它,谁知道,也许我们正在关闭-1而不是真正的关闭套接字. (注意关闭网络级别和关闭文件描述符级别之间的区别,这需要单独的关闭调用.)

这也可以通过移动到民意调查来处理,但 *** 作系统强加了一些其他限制,使这条路线非常具有挑战性.

带外数据

你说服务器正在“发送”数据.如果这意味着使用send调用发送数据(而不是写调用),请使用strace确定send flags参数.如果使用MSG_OOB标志,则数据将作为带外数据到达 – 在您将fds副本作为另一个参数传递之前,您的选择调用将不会注意到这些数据.

fd_set fds_copy = fds;select( m_socket + 1,&fds_copy,timeout == -1 ? 0 : &tv )

过程饥饿

如果该框严重超载,则服务器正在执行而没有任何阻塞调用,并且具有实时优先级(使用top来检查) – 而客户端不是 – 客户端可能会被饿死.

暂停过程

理论上,客户端可能会使用SIGStop停止.您可能知道是否是这种情况,在某个地方按下ctrl-Z或者让某个特定的进程在客户端上执行控制而不是自己启动它.

总结

以上是内存溢出为你收集整理的c – 套接字选择中可能导致死锁原因全部内容,希望文章能够帮你解决c – 套接字选择中可能导致死锁的原因所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址:https://54852.com/langs/1226053.html

(0)
打赏 微信扫一扫微信扫一扫 支付宝扫一扫支付宝扫一扫
上一篇 2022-06-05
下一篇2022-06-05

发表评论

登录后才能评论

评论列表(0条)

    保存