如何检测其他程序关闭的eventfd文件描述符

how to detect eventfd file descriptor close by other program

本文关键字:eventfd 文件 描述 程序 何检测 检测 其他      更新时间:2023-10-16

我有一个客户端/服务器通过eventfd进行通信。如果客户端或服务器调用close(fd),我希望另一端能找到(就像文件描述符现在关闭一样)。我尝试使用超时为非零的select,它总是返回0,即超时。我看到有人建议使用fcntl,但它似乎也不起作用。有什么建议吗?

添加详细信息(省略了非重要部件代码,您可以在此处查看如何交换文件描述符详细代码:它是多进程应用程序。服务器进程通过调用创建事件fd

 struct msghdr control_message;
 int fd = eventfd(0,0);
 *CMSG_DATA(control_message) = fd;
 message.msg_control = &control_message;
 sendmsg(socket_fd, & message,0); //send this to client

来自客户端:

 recvmsg(socket_fd, & message,0);
 //loop using CMSG_NXTHDR(&message, control_message)
 int fd = *(int *) CMSG_DATA(contro_message);

然后在服务器端:

 close(fd);

在客户端:int rc;rc=dup2(fd,fd);

rc从不无效。

是否正在检查已关闭的文件描述符?这个怎么样?

#include <errno.h>
#include <stdio.h>
#include <string.h>
static void checkit ()
{
    int     rc;
    rc = dup2(2, 2);
    if ( rc == -1 )
            printf("error %d on dup2(2, 2): %sn", errno, strerror(errno));
    else
            printf("dup2 successfuln");
    write(2, "still workingn", 14);
}
int main (int argc, char **argv)
{
    int     rc;
    checkit();
    close(2);
    checkit();
    return  0;
}

运行它会生成以下输出:

dup2 successful
still working
error 9 on dup2(2, 2): Bad file descriptor

如果这是一个使用轮询的多线程应用程序,并且您希望在另一个线程关闭文件描述符时返回轮询,则POLLERR、POLLHUP或POLLNVAL可能会有所帮助。

使用轮询的多线程版本

这里有一个示例,展示了如何在多线程程序中通过轮询(POLLNVAL是事件)来检测关闭的fd:

#include <errno.h>
#include <poll.h>
#include <pthread.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static void *run_poll (void *arg)
{
    struct pollfd   fds[1];
    int             rc;
    fds[0].fd = 2;
    fds[0].events = POLLERR | POLLHUP | POLLNVAL;
            //
            // Poll indefinitely
            //
    printf("starting polln");
    fflush(stdout);
    rc = poll((struct pollfd *) &fds, 1, -1);
    if ( rc == -1 )
    {
            printf("POLL returned error %d: %sn", errno, strerror(errno));
    }
    else
    {
            printf("POLL returned %d (revents = 0x%08x): %s %s %sn",
                   rc,
                   fds[0].revents,
                   ( ( fds[0].revents & POLLERR  ) ? "pollerr" : "noerr" ),
                   ( ( fds[0].revents & POLLHUP  ) ? "pollhup" : "nohup" ),
                   ( ( fds[0].revents & POLLNVAL ) ? "pollnval" : "nonval" ));
    }
    return  NULL;
}
int main (int argc, char **argv)
{
    pthread_t       thread;
    int             rc;
    rc = pthread_create(&thread, NULL, run_poll, NULL);
    usleep(100);
    printf("closing stderrn");
    close(2);
    usleep(100);
    return  0;
}

这会生成输出

starting poll
closing stderr
POLL returned 1 (revents = 0x00000020): noerr nohup pollnval