为什么在设置 SO_RCVTIMEO 时 recv returns -1 和 errno=EINTR?

Why recv returns -1 and errno=EINTR when set SO_RCVTIMEO?

此问题仅在套接字设置超时时发生SO_RCVTIMEO。

recv 应该阻塞 3 秒。但它 return 是因为 EINTR 一旦另一个线程启动。

如果我 运行 线程 t2,线程 t1 中的 recv 将 return -1 不阻塞并设置 errnoEINTR.

但是线程t1中的recv在线程t2未启动时正常运行,它只是阻塞了3秒。

如果线程 t2 运行 早于线程 t1recv 也能正常工作。

我用SlickEdit 或gdb 调试时发现每次都失败。但是当它 运行 在终端中时可以正常工作。

代码如下:

test.cpp: link -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();
}

这是一个潜在的错误

bzero(&(server_addr.sin_zero),8);

应该是

bzero(&(server_addr.sin_zero), sizeof(server_addr.sin_zero));

linux there is a method to handle all, example 添加信号处理程序以查明错误是什么。

请参阅 "Some programmer dude"

对 EINTR 的评论

调试器 (gdb),除非可以 set/modify 异步断点,否则需要停止目标(您的任务),设置断点,然后恢复它。 要停止它,它可以发送 SIGINT,这将导致系统上的 EINTR 阻塞调用。

如果您使用 GNU C 库,您可以使用 TEMP_FAILURE_RETRY 宏,请参阅此 post: TEMP_FAILURE_RETRY and __USE_GNU