仅当使用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();
}
答案 0 :(得分:1)
这是一个潜在的错误
bzero(&(server_addr.sin_zero),8);
应该是
bzero(&(server_addr.sin_zero), sizeof(server_addr.sin_zero));
答案 1 :(得分:0)
请参阅“一些程序员老兄”对EINTR的评论
除非可以异步设置/修改断点,否则调试器(gdb)需要停止目标(您的任务),设置断点,然后恢复它。 要停止它,它可能会发送SIGINT,这将导致系统上的EINTR被阻止。
如果您使用GNU C库,则可以使用TEMP_FAILURE_RETRY宏,请参阅以下文章: TEMP_FAILURE_RETRY and __USE_GNU