(请高手救命啊!在线等)Socket Send的时候,不停的得到EINTR错误返回, 请问是为什么?

kkong2000 2003-08-19 09:58:51
在Redhat7.3下,多线程多CPU,在非常高频率Socket端口Send操作的时候,大概是1000次/秒以上, 持续出现EINTR错误。 有高手知道原因,或者知道怎么解决,或者知道相关网上信息的,请帮忙告知。分数不是问题!

先谢谢了!
...全文
594 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
westar 2003-08-21
  • 打赏
  • 举报
回复
up
fierygnu 2003-08-21
  • 打赏
  • 举报
回复
看了一下你的代码,
if (send_ret < 0)
{
if (errno==EPIPE)
{
(writer->FDS)->shutdown(sciNode->fd);
scoNode = new SCMQNode;
scoNode->fd = sciNode->fd;
scoNode->Action = CLOSEFD_RECV;
scoNode->len = 0;
scoNode->msg = NULL;
(writer->SCIMsgQueue)->put(scoNode);
}
if (errno==EINTR) //这里应该用else if
{
sendIntrFlag = true;
continue;
}
}
如果EPIPE处理分支里的代码产生一个错误,此错误会设置errno,如果是EINTR就会进入EINTR的处理分支。改成else if试试。
fierygnu 2003-08-21
  • 打赏
  • 举报
回复
楼主结贴了,能不能明示一下到底是什么问题,我们也学习学习啊。
fierygnu 2003-08-20
  • 打赏
  • 举报
回复
strace报告有什么问题吗?
kkong2000 2003-08-20
  • 打赏
  • 举报
回复
还是没有实质性的进展,有高手有类似的经历吗?请赐教经验啊!
kkong2000 2003-08-20
  • 打赏
  • 举报
回复
可是我程序里面除了启动时,用来成为daemon进程时,调用了2次fork,其他没有fork的调用了。我猜测是不是,在一定条件下rt_sigsuspend的返回值EINTR,覆盖了EBADF?
fierygnu 2003-08-20
  • 打赏
  • 举报
回复
In a multithreaded application, EINTR may be returned whenever another thread or LWP calls fork(2).
我想你的问题就出现在这里。限制fork数目试试。
kkong2000 2003-08-20
  • 打赏
  • 举报
回复
strace报告发现应该返回EBADF的情况下,返回了EINTR的错误。 我的程序中对于EBADF的错误处理是丢弃这个数据。
正常返回errno = 32的时候的strace:
******************************************************************************
kill(19890, SIGRTMIN) = 0
send(430, "\217\1\0\10\27\374@3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 128, 0x4000) = -1 EPIPE (Broken pipe)
rt_sigprocmask(SIG_SETMASK, NULL, [RTMIN], 8) = 0
rt_sigsuspend([] <unfinished ...>
--- SIGRTMIN (Real-time signal 0) ---
<... rt_sigsuspend resumed> ) = -1 EINTR (Interrupted system call)
sigreturn() = ? (mask now [RTMIN])
*******************************************************************************

错误返回Errno = 4的时候的strace:
*******************************************************************************
kill(19720, SIGRTMIN) = 0
send(82, "\217\1\0\10\27\374@3\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"..., 128, 0x4000) = -1 EBADF (Bad file descriptor)
rt_sigprocmask(SIG_SETMASK, NULL, [RTMIN], 8) = 0
rt_sigsuspend([] <unfinished ...>
--- SIGRTMIN (Real-time signal 0) ---
<... rt_sigsuspend resumed> ) = -1 EINTR (Interrupted system call)
sigreturn() = ? (mask now [RTMIN])
******************************************************************************

wwwunix 2003-08-19
  • 打赏
  • 举报
回复
另外,你还可以注册一个信号处理函数,看看是什么信号中断了你的系统调用.
wwwunix 2003-08-19
  • 打赏
  • 举报
回复
出现EINTR的原因是进程执行了一个低速系统调用而阻塞期间捕捉到一个信号,则该系统调用就被中断不再继续执行.
建议:当你接受到EINTR后,重发刚才数据.或者将你不用的信号屏蔽掉.
fierygnu 2003-08-19
  • 打赏
  • 举报
回复
你的程序里使用信号了吗?
kkong2000 2003-08-19
  • 打赏
  • 举报
回复
没有较好的排版,请海涵。 另:发送是Block模式的。
void* SCMsgWriter::thread_func(void* data)
{
SCMsgWriter* writer = *(SCMsgWriter**)data;
int send_ret=0;
bool sendIntrFlag = false;
struct SCMQNode* sciNode=NULL;
struct SCMQNode* scoNode=NULL;

try
{
while(1)
{
if (sendIntrFlag == false)
{
sciNode = writer->SCOMsgQueue->get();
if (sciNode == NULL) continue;
}
else
{
sendIntrFlag = false;
}

if (sciNode->Action == MESSAGE_SEND)
{
send_ret = 0;
send_ret = send(sciNode->fd, sciNode->msg, sciNode->len, MSG_NOSIGNAL);

if (send_ret < 0)
{
if (errno==EPIPE)
{
(writer->FDS)->shutdown(sciNode->fd);
scoNode = new SCMQNode;
scoNode->fd = sciNode->fd;
scoNode->Action = CLOSEFD_RECV;
scoNode->len = 0;
scoNode->msg = NULL;
(writer->SCIMsgQueue)->put(scoNode);
}
if (errno==EINTR)
{
sendIntrFlag = true;
continue;
}
}
else if (send_ret>=0 && send_ret<sciNode->len )
{
(writer->FDS)->shutdown(sciNode->fd);
scoNode = new SCMQNode;
scoNode->fd = sciNode->fd;
scoNode->Action = CLOSEFD_RECV;
scoNode->len = 0;
scoNode->msg = NULL;
(writer->SCIMsgQueue)->put(scoNode);
}
}
else if ((sciNode->Action==CLOSEFD_SEND) || (sciNode->Action==CHECK_VERSION))
{
send_ret = 0;
send_ret = send(sciNode->fd, sciNode->msg, sciNode->len, MSG_NOSIGNAL);

if (send_ret < 0)
{
if (errno==EINTR)
{
continue;
}
}
writer->FDS->shutdown(sciNode->fd);
}

delete [] sciNode->msg;
delete sciNode;
sciNode = NULL;
}
}
catch(...)
{
TRACE("SCMsgWriter Exception Exit!", LEVEL_CRITICAL);
}

TRACE("SCMsgWriter Return!", LEVEL_CRITICAL);
return NULL;
}
kkong2000 2003-08-19
  • 打赏
  • 举报
回复
没有较好的排版,请海涵。 另:发送是Block模式的。
void* SCMsgWriter::thread_func(void* data)
{
SCMsgWriter* writer = *(SCMsgWriter**)data;
int send_ret=0;
bool sendIntrFlag = false;
struct SCMQNode* sciNode=NULL;
struct SCMQNode* scoNode=NULL;

try
{
while(1)
{
if (sendIntrFlag == false)
{
sciNode = writer->SCOMsgQueue->get();
if (sciNode == NULL) continue;
}
else
{
sendIntrFlag = false;
}

if (sciNode->Action == MESSAGE_SEND)
{
send_ret = 0;
send_ret = send(sciNode->fd, sciNode->msg, sciNode->len, MSG_NOSIGNAL);

if (send_ret < 0)
{
if (errno==EPIPE)
{
TRACEX_LOCK;
TRACEX_UNLOCK;
(writer->FDS)->shutdown(sciNode->fd);
scoNode = new SCMQNode;
scoNode->fd = sciNode->fd;
scoNode->Action = CLOSEFD_RECV;
scoNode->len = 0;
scoNode->msg = NULL;
(writer->SCIMsgQueue)->put(scoNode);
}
if (errno==EINTR)
{
sendIntrFlag = true;
continue;
}
}
else if (send_ret>=0 && send_ret<sciNode->len )
{
(writer->FDS)->shutdown(sciNode->fd);
scoNode = new SCMQNode;
scoNode->fd = sciNode->fd;
scoNode->Action = CLOSEFD_RECV;
scoNode->len = 0;
scoNode->msg = NULL;
(writer->SCIMsgQueue)->put(scoNode);
}
}
else if ((sciNode->Action==CLOSEFD_SEND) || (sciNode->Action==CHECK_VERSION))
{
send_ret = 0;
send_ret = send(sciNode->fd, sciNode->msg, sciNode->len, MSG_NOSIGNAL);

if (send_ret < 0)
{
TRACEX_LOCK;
TRACEX(LEVEL_MINOR)<<"send error! errno is "<<errno<<endl;
TRACEX_UNLOCK;
if (errno==EINTR)
{
continue;
}
}
writer->FDS->shutdown(sciNode->fd);
}

delete [] sciNode->msg;
delete sciNode;
sciNode = NULL;
}
}
catch(...)
{
TRACE("SCMsgWriter Exception Exit!", LEVEL_CRITICAL);
}

TRACE("SCMsgWriter Return!", LEVEL_CRITICAL);
return NULL;
}
tomascat 2003-08-19
  • 打赏
  • 举报
回复
看看发送的字节和头计数是否相符!
wwwunix 2003-08-19
  • 打赏
  • 举报
回复
能否将你出错部分的代码帖上来?
kkong2000 2003-08-19
  • 打赏
  • 举报
回复
不是的,我在发送数据的时候,发生EINTR错误的!
(感谢你的关注)
wwwunix 2003-08-19
  • 打赏
  • 举报
回复
你是不是在调用select()时出现的EINTR错误?
kkong2000 2003-08-19
  • 打赏
  • 举报
回复
帮忙顶的,一定有分相报,谢谢啦!
kkong2000 2003-08-19
  • 打赏
  • 举报
回复
我比较菜,还不会用strace,看来要研究一下。
fierygnu 2003-08-19
  • 打赏
  • 举报
回复
用strace跟踪你的应用,看看发生EINTR时是怎么回事?
加载更多回复(6)

23,125

社区成员

发帖
与我相关
我的任务
社区描述
Linux/Unix社区 应用程序开发区
社区管理员
  • 应用程序开发区社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧