c++ - 如何等待 n 秒才能打开命名管道?

标签 c++ linux named-pipes polling

我有一个程序,当我在 N(假设 30)秒后无法打开管道进行读取时,我想退出该程序。

我的代码适用于阻塞名称管道,我无法更改它。

我了解 select() 和 poll(),但如果不将管道变成非阻塞,我就无法让它们工作。

这是我到目前为止的代码:

struct pollfd fds[1];
int pol_ret;

fds[0].fd = open(pipe_name, O_RDONLY /* | O_NONBLOCK */);

if (fds[0].fd < 0)
{
    // send_signal_to_parent();
    std::cout << "error while opening the pipe for read, exiting!" << '\n';
    return -1;
}

fds[0].events = POLLIN;

int timeout_msecs = 30000;    //  (30 seconds)
pol_ret = poll(fds, 1, timeout_msecs);

std::cout << "poll returned: "<< pol_ret << '\n';
 if (pol_ret == 0)
 {
     std::cout << "im leaving" << '\n';
     return -1;    
 }

如何只等待 30 秒管道打开进行读取?

我正在运行 Linux,特别是 debian。

最佳答案

使用信号处理程序设置计时器并等待 fifo 上的调用打开。 如果打开失败并显示 errno=EINTR 并且您的处理程序运行,则 open 调用被计时器中断,即超时。

示例代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/stat.h>
#include <signal.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>

volatile sig_atomic_t abort_eh;
void handler(int Sig)
{
    abort_eh = 1;
}

int main()
{
    struct sigaction sa;
    sa.sa_flags = 0;
    sa.sa_handler = handler;
    sigemptyset(&sa.sa_mask);
    sigaction(SIGALRM,&sa,0);

    //try to ensure the fifo exists
    (void)mkfifo("fifo",0600);

    //open with a timeout of 1s
    alarm(1);

    int fd;
    do{
        if (0>(fd=open("fifo",O_RDONLY)))
            if(errno==EINTR){
                if(abort_eh) return puts("timed out"),1;
                else continue; //another signal interrupted it, so retry
            }else return perror("open"),1;
    }while(0);

    alarm(0); //cancel timer
    printf("sucessfully opened at fd=%d\n", fd);

}

setitimertimer_create/timer_settime 提供比 alarm 更好、更细粒度的计时器。他们还可以将计时器设置为重复,这允许您在第一个信号“错过”的情况下重新发出信号(即,在输入 open 调用之前运行,因此无法打破可能无限期阻塞的系统调用)。

关于c++ - 如何等待 n 秒才能打开命名管道?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55657490/

相关文章:

linux - 应用程序中的符号链接(symbolic link)生命周期

c# - 更改命名管道访问权限

c++ - GLE 997 :Overlapped I/O operation is in progress

c++ - 阴影体积 - 寻找轮廓

C++ 将运算符放在类末尾的目的是什么?

c++ - 对于非管理员用户,localhost 上的 HttpAddUrl 失败

C++ 泛型类设计,其方法返回子类

linux - 如何将 android studio 添加到 i3wm 的 rofi 菜单中?

linux - 我有名为 pack1 - pack255 的目录。我可以使用什么命令删除 pack1-55?

.net - 如何使命名管道在 C++ 和 .NET 之间工作?