2016-10-08 8 views
0

Я создаю библиотеку сообщений, которая берет фильтр и использует его для чтения и записи. Протокол определяет тайм-ауты, поэтому я хочу их использовать.FILE * чтение с таймаутом

Я использую fread(3) и fwrite(3). Я слышал о select(2), и это то, что я ищу, за исключением того, что он использует файловые дескрипторы, а не libc filestreams. Я хочу поддерживать настраиваемые потоки потоков, созданные с помощью fopencookie(3), полезные для тестов и прочего. Я попытался создать SIGALRM с alarm(2), чтобы получить ошибку EINTR из fread(3) (настройки обратного вызова для SIGALRM с помощью signal(2)), но это не остановит fopen вызова, как ожидалось ...

Спасибо заранее для любого решения ,

EDIT: Таким образом, похоже, что это работает .. но только один раз. На втором вызове, он не ... Оо

/** 
* sigalrm_handler: 
* Shut up SIGALRM. 
* 
* @arg code  signal code (always SIGALRM) 
*/ 

static __thread jmp_buf env_alrm; 
static void sigalrm_handler(int signo) 
{ 
    (void)signo; 
    /* restore env */ 
    longjmp(env_alrm, 5); 
} 

/** 
* _p7_fread: 
* Read file with timeout. 
* 
* @arg ptr   the buffer pointer 
* @arg size  the size of an item 
* @arg nitems  the number of items in the buffer 
* @arg stream  the stream 
* @arg timeout  the timeout (seconds) 
* @return    the number of read bytes 
*/ 

size_t _p7_fread(void *ptr, size_t size, size_t nitems, FILE *stream, 
    int timeout) 
{ 
    size_t read_count = 0; 

    /* set long jump */ 
    int val = setjmp(env_alrm); 
    if (!val) { 
    /* setup signal handler */ 
     if (signal(SIGALRM, &sigalrm_handler) == SIG_ERR) 
      return (0); 

     /* setup alarm */ 
     alarm(timeout); 

     /* read */ 
     read_count = fread(ptr, size, nitems, stream); 
    } else 
     errno = EINTR; 

    /* unset signal handler and alarm */ 
    signal(SIGALRM, NULL); 
    alarm(0); 

    /* return */ 
    return (read_count); 
} 

Опять же, спасибо за любую помощь ^^

ответ

0

функции: fdopen() получит вы подаете указатели из файловых дескрипторов.

Затем вы можете использовать эту функцию: select() с указателями файлов, которые были возвращены с fdopen().

+0

А как насчет внутренних буферов в структуру FILE *? А как насчет фидов, у которых нет файлового дескриптора (я думаю о тех, которые созданы с помощью fopencookie)? – Cakeisalie5

+0

это от: <> "Функция fdopen() связывает поток с существующим файловым дескриптором, fd. Режим потока (одно из значений« r »,« r + »,« w »,« w + », «a», «a +») должны быть совместимы с режимом файлового дескриптора. Индикатор позиции файла для нового потока установлен в значение, принадлежащее fd, а индикаторы ошибок и конца файла очищаются. Режимы " w "или" w + "не вызывают усечения файла. Дескриптор файла не дублируется и будет закрыт, когда поток, созданный fdopen(), будет закрыт. Результат применения fdopen() для объекта общей памяти undefined. " – user3629249

+0

Итак, я попробовал' select' и 'fileno'. Но факт: 'fileno' возвращает -1 в пользовательский поток, созданный с помощью' fopencookie', поэтому я не могу использовать 'select' с ним. И если я хочу проверить тайм-ауты с пользовательскими фильтрами ... так что это не сработает для меня. :/ – Cakeisalie5