linux - 可以使用未添加到选择集中的描述符调用 FD_ISSET 吗?

标签 linux unix select

我正在调试一个通常工作正常但在重负载下因段错误而死的选择循环。我发现该程序有时会为未添加到选择集中的(正确的)描述符调用 FD_ISSET()。就像下面的片段:

#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

void die(const char* msg)
{
    fprintf(stderr, "fatal %s", msg);
    exit(1);
}

int main(void)
{
    FILE* file = fopen("/tmp/test", "r");
    if (file == NULL)
        die("fopen");

    int file_fd = fileno(file);
    fd_set read_fds;
    int max_fd = 0;

    FD_ZERO(&read_fds);
    // Only stdin is added to read_fds.
    FD_SET(0, &read_fds);

    if (select(max_fd + 1, &read_fds, NULL, NULL, NULL) < 0)
        die("select");
    if (FD_ISSET(0, &read_fds))
        printf("Can read from 0");
    // !!! Here FD_ISSET is called with a valid descriptor that was 
    // not added to read_fds.
    if (FD_ISSET(file_fd, &read_fds))
        printf("Can read from file_fd");
    return 0;
}

很明显,用 !!! 标记的检查不应该返回 true,但它是否可能是 SEGFAULT 的原因?当我在 valgrind 下运行这个片段时,没有报告错误,但是当我在 valgrind 下运行我的负载测试时,我偶尔会看到如下错误:

==25513== Syscall param select(writefds) points to uninitialised byte(s)
==25513==    at 0x435DD2D: ___newselect_nocancel (syscall-template.S:82)

最佳答案

FD_ISSET() 测试文件描述符是否是集合 read_fds 的一部分。这意味着 FD_ISSET 不应导致段错误。

尝试在调用 FD_ISSET 之前检查 errno 值集。 select 应该导致段错误。

同时检查 file_fd 值是否不大于 FD_MAX

关于linux - 可以使用未添加到选择集中的描述符调用 FD_ISSET 吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13705454/

相关文章:

linux - 如何在一台机器上构建 samba 并在另一台机器上安装二进制文件?

linux - Unix 中的内置命令

python - 如何从python设置文件的最后修改时间?

javascript - 哪个更快?按ID选择,还是按索引选择?

html - <select> 和 :after with CSS in WebKit 的问题

mysql - MariaDB 嵌套选择

linux - 作业完成时执行命令

linux - 我怎样才能启动一个不是原始进程子进程的新进程?

c++ - 使用移位运算符进行奇怪的相等性检查

c - UNIX 中的管道不应该是单向的吗?