此问题仅在使用 SO_RCVTIMEO 设置套接字超时时发生。
recv
应该阻塞 3 秒。但是一旦另一个线程启动,它就会因为 EINTR 而返回。
如果我运行线程 t2
, recv
在线程中t1
将返回 -1
没有阻塞并设置errno
至 EINTR
.
但是recv
在线程中t1
线程 t2
时正常运行没有启动,它只是阻塞 3 秒。
如果线程t2
在线程 t1
之前运行, recv
也能正常工作。
当我用 SlickEdit 或 gdb 调试时,我发现它每次都失败。但在终端中运行时可以正常工作。
代码如下:
test.cpp:链接-pthread
使用 <thread>
或者线程抛出异常
#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();
}
最佳答案
请参阅“一些程序员老兄”对 EINTR 的评论
除非可以异步设置/修改断点,否则调试器 (gdb) 需要停止目标(您的任务),设置断点,然后恢复它。 要停止它,它可以发送 SIGINT,这会导致系统上的 EINTR 阻塞调用。
如果您使用 GNU C 库,您可以使用 TEMP_FAILURE_RETRY 宏,请参阅这篇文章: TEMP_FAILURE_RETRY and __USE_GNU
关于c++ - 为什么 recv 在设置 SO_RCVTIMEO 时返回 -1 和 errno=EINTR?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51666259/