Как я могу ждать n секунд для открытия именованного канала? - PullRequest
0 голосов
/ 12 апреля 2019

У меня есть программа, которую я хочу закрыть, когда я не могу открыть канал для чтения через 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.

1 Ответ

0 голосов
/ 12 апреля 2019

Настройте таймер с помощью обработчика сигнала и дождитесь открытия вызова на 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);

}

setitimer или timer_create / timer_settime обеспечивают более точные таймеры лучше, чем alarm.Они также имеют возможность установки таймера для повторения, что позволяет вам выполнять повторную сигнализацию в случае, если первый сигнал «пропущен» (т. Е. Был запущен незадолго до того, как был введен вызов open, и, таким образом, не смог прервать потенциально бесконечный блокирующий системный вызов).

...