C++ 当设置为-1时,为什么recv返回-1且errno=EINTR?
此问题仅在使用SO_RCVTIMEO设置套接字超时时出现C++ 当设置为-1时,为什么recv返回-1且errno=EINTR?,c++,linux,recv,setsockopt,C++,Linux,Recv,Setsockopt,此问题仅在使用SO_RCVTIMEO设置套接字超时时出现 recv应阻止3秒。但它会在另一个线程启动时返回,因为EINTR 如果我运行线程t2,线程t1中的recv将返回-1而不阻塞,并将errno设置为EINTR 但是线程t1中的recv功能正常,当线程t2未启动时,它只会阻塞3秒钟 如果线程t2在线程t1之前运行,recv也能正常工作 我发现每次使用SlickEdit或gdb进行调试时,它都会失败。但在终端运行时工作正常 以下是代码: test.cpp:链接-pthread使用或线程抛出异常
recv
应阻止3秒。但它会在另一个线程启动时返回,因为EINTR
如果我运行线程t2
,线程t1
中的recv
将返回-1
而不阻塞,并将errno
设置为EINTR
但是线程t1
中的recv
功能正常,当线程t2
未启动时,它只会阻塞3秒钟
如果线程t2
在线程t1
之前运行,recv
也能正常工作
我发现每次使用SlickEdit或gdb进行调试时,它都会失败。但在终端运行时工作正常 以下是代码: test.cpp:链接
-pthread
使用
或线程抛出异常
#include<unistd.h>
#include<netdb.h>
#include<string.h>
#include<thread>
int socket_fd;
sockaddr_in server_addr;
void recvThread()
{
char pData[4096];
int len = recv(socket_fd,pData,4096,0);
if(len<=0)
{
printf("len:%d\n",len);
printf("errno:%d\n",errno);
}
}
void otherThread()
{
while(1)
{
sleep(1);
}
}
int main()
{
hostent *host;
if((host=gethostbyname("127.0.0.1"))==NULL)
{
return 1;
}
memset(&server_addr, 0, sizeof(sockaddr_in));
server_addr.sin_family=AF_INET;
server_addr.sin_port=htons(8887);
server_addr.sin_addr=*((in_addr*)host->h_addr);
bzero(&(server_addr.sin_zero),8);
socket_fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
timeval timeout = {3,0};
setsockopt(socket_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeval));
if(connect(socket_fd, (sockaddr*)&server_addr, sizeof(server_addr))<0)
{
return 1;
}
std::thread t1(recvThread);
std::thread t2(otherThread);
t1.join();
t2.join();
}
#包括
#包括
#包括
#包括
int-socket_-fd;
服务器地址中的sockaddr\u;
void recvThread()
{
char-pData[4096];
int len=recv(插座fd,pData,4096,0);
if(lenh_addr);
bzero(&(服务器地址sin_zero),8);
socket\u fd=socket(PF\u INET、SOCK\u STREAM、IPPROTO\u TCP);
timeval timeout={3,0};
setsockopt(socket_fd、SOL_socket、SO_RCVTIMEO和timeout、sizeof(timeval));
如果(connect(socket\u fd,(sockaddr*)和server\u addr,sizeof(server\u addr))这是一个潜在的错误
bzero(&(server_addr.sin_zero),8);
应该是
bzero(&(server_addr.sin_zero), sizeof(server_addr.sin_zero));
添加信号处理程序以找出错误是什么,因为有一种方法可以处理所有错误。请参阅“一些程序员”对EINTR的评论
除非调试器(gdb)可以异步设置/修改断点,否则它需要停止目标(任务),设置断点,然后继续。
要停止它,它可能会发送SIGINT,这将导致系统阻塞呼叫上的EINTR
如果您使用GNU C库,您可以使用TEMP\u FAILURE\u RETRY宏,请参阅本文:
你知道EINTR
的意思吗?请从阅读开始。我不知道它为什么会被信号中断?std::thread t2(otherThread)调用将发送一个信号?如果你的第二个线程没有执行问题中所示的任何操作,这将不会导致向进程发送信号(但会导致浪费大量CPU周期)。它可以是任何信号,如果没有合适的命令,我们根本无法了解更多。我更新了那里的所有代码。因为我无法从内部机器复制,所以可能会有一些键入错误。此代码可以显示我的要求。奇怪的部分是:通过交换std:thread t1 t2的调用顺序,recv可以正常工作。bze在上一次memset
调用之后,甚至不需要ro
调用。我删除了bzero,但没有任何更改。我尝试了一些方法使其工作。甚至睡眠(1)在std::thread t1和recv block 1sec之后,然后recv在t2启动时返回-1。我发现每次使用SlickEdit或gdb进行调试时它都会失败。但当它在终端中运行时会正常工作。