опрос по FIFO немедленно возвращается в HP-UX

Я пытаюсь использовать poll(2) для FIFO. на разных платформах, но (по сравнению с Linux, Solaris, AIX) поведение HP-UX несколько отличается от других платформ.

Ниже код создает FIFO (именованный канал) и опрашивает его с тайм-аутом 3 с. Поскольку этот код не записывает в FIFO, я ожидаю, что результат опроса будет 0.

#include <fcntl.h>
#include <poll.h>
#include <signal.h>
#include <sys/stat.h>
#include <sys/types.h>

#include <unistd.h>
#include <errno.h>
#include <inttypes.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#if defined(CLOCK_MONOTONIC)
#define MY_CLOCK_TIME CLOCK_MONOTONIC
#elif defined(CLOCK_REALTIME)
#define MY_CLOCK_TIME CLOCK_REALTIME
#else
#error neither CLOCK_REALTIME nor CLOCK_MONOTONIC defined.
#endif

#define HANDLE_ERROR(expr, msg) \
    do                          \
    {                           \
        if ((expr) < 0)         \
        {                       \
            perror(msg);        \
            exit(EXIT_FAILURE); \
        }                       \
    } while (0);

namespace {
const char pipename[] = "pipe";

template <size_t N>
struct type_of_size
{
    typedef char type[N];
};

template <typename T, size_t Size>
typename type_of_size<Size>::type& sizeof_array_helper(T (&)[Size]);

#define SIZE_OF_ARR(pArray) sizeof(sizeof_array_helper(pArray))

int my_unlink(const char* name)
{
    int result = unlink(name);
    if (result < 0)
    {
        if (errno == ENOENT)
        {
            result = 0;
            errno = 0;
        }
    }
    return result;
}

double timediff(const struct timespec& t1, const struct timespec& t2)
{
    return static_cast<double>(static_cast<int64_t>(
               (t1.tv_sec - t2.tv_sec) * 1000000000LL + (t1.tv_nsec - t2.tv_nsec))) /
           1000000000LL;
}
} // namespace

int main()
{
    HANDLE_ERROR(my_unlink(pipename), "unlink");
    HANDLE_ERROR(mkfifo(pipename, 0600), "mkfifo");

    int result = 0;
    int poll_timeout = 3000; // 3s
    struct timespec before;
    memset(&before, 0, sizeof(struct timespec));
    struct timespec after;
    memset(&after, 0, sizeof(struct timespec));

    int fd = open(pipename, O_RDONLY | O_NONBLOCK);
    HANDLE_ERROR((fd < 0), "open");
    pollfd fds[1];
    memset(fds, 0, sizeof(pollfd) * SIZE_OF_ARR(fds));
    fds[0].fd = fd;
    fds[0].events = POLLIN;

    HANDLE_ERROR(clock_gettime(MY_CLOCK_TIME, &before), "clock_gettime");

#ifdef USE_FAKE_OPEN
    int fakeopen_fd = open(pipename, O_WRONLY | O_NONBLOCK);
    HANDLE_ERROR((fakeopen_fd < 0), "open");
#endif

    result = poll(fds, SIZE_OF_ARR(fds), poll_timeout);
    memset(&after, 0, sizeof(struct timespec));
    HANDLE_ERROR(clock_gettime(MY_CLOCK_TIME, &after), "clock_gettime");
    double interval = timediff(after, before);
    printf("call interval: %.3f, poll result: %d, errr: %s\n", interval, result, strerror(errno));

#ifdef USE_FAKE_OPEN
    close(fakeopen_fd);
#endif

    close(fd);
    return (interval > 2.0) ? EXIT_SUCCESS : EXIT_FAILURE;
}

В Linux, Solaris 10, AIX 7.1 он работает должным образом (call interval: 3.000, poll result: 0, errr: Error 0), но HP-UX (11.31) не подчиняется параметру тайм-аута и немедленно возвращается (call interval: 0.000, poll result: 1, errr: Error 0).

Если я открываю FIFO для записи перед опросом для чтения (определить USE_FAKE_OPEN), он работает, как и ожидалось, даже для HP-UX.

  1. Что делает это поведение?

  2. Совместим ли опрос HP-UX с POSIX?


person Byoungchan Lee    schedule 19.04.2018    source источник


Ответы (1)


Хорошо, есть правило программирования, которое «Это всегда ваша вина (выбор не нарушен)», но HP сообщает, что их опрос FIFO не работает в их документация по исправлению HP-UX PHKL_41419:

poll(2) устанавливает событие POLLIN (данные готовы к чтению), даже если на другом конце нет записи, когда FIFO открыт с O_RDONLY в неблокирующем режиме (установлено O_NONBLOCK).

Дело закрыто.

person Byoungchan Lee    schedule 23.04.2018