This problem only hapens when socket is set timeout with SO_RCVTIMEO.
recv
should block for 3sec. But it returns because of EINTR as soon as another thread starts.
If I run thread t2
, recv
in thread t1
will return -1
without blocking and sets errno
to EINTR
.
But recv
in thread t1
functions normally when thread t2
is not started, it just blocks for 3 seconds.
If thread t2
runs before thread t1
, recv
also works properly.
I found it fails every time when I was debuging with SlickEdit or gdb. But works properly when it runs in terminal.
Here is code:
test.cpp: link -pthread
to use <thread>
or thread throws exception
#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();
}
See comment on EINTR from "Some programmer dude"
The debugger (gdb), unless can set/modify breakpoints asynchronously, needs to stop the target (your task), set the breakpoints, then resume it. To stop it it could send SIGINT, which would thus cause EINTR on your system blocked calls.
If you using GNU C library you could use TEMP_FAILURE_RETRY macro, see this post: TEMP_FAILURE_RETRY and __USE_GNU