c++ - 为什么 recv 在设置 SO_RCVTIMEO 时返回 -1 和 errno=EINTR?

标签 c++ linux recv setsockopt

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

recv应该阻塞 3 秒。但是一旦另一个线程启动,它就会因为 EINTR 而返回。

如果我运行线程 t2 , recv在线程中t1将返回 -1没有阻塞并设置errnoEINTR .

但是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/

相关文章:

c++ - 如何使用 CMake 订购/设计使用更高的共享库包括

linux - 终端中未显示某些 TCP 状态

c - Debug模式标志始终运行

c - 读取 TCP 套接字中的 buff

c++ - QT鼠标事件处理问题

c++ - 在 VC++ 中调试时幕后发生了什么

c++ - 找不到 LMDB(缺少 : LMDB_INCLUDE_DIR LMDB_LIBRARIES)

java - 未找到 JDK。请验证 STUDIO_JDK、JDK_HOME 或 JAVA_HOME 环境变量是否指向有效的 JDK 安装

c++ - 使用epoll_wait时如何正确读取数据

Python:停止套接字接收进程