Чтение и удаление из FIFO в C

Я создаю сервер, который общается со своими клиентами через FIFO.

Пока мне удалось создать FIFO, запустить новый поток, как только сообщение поступит в FIFO, и вывести сообщение из потока.

Проблема в том, что как только клиент что-то записывает в канал, сервер просто бесконечно печатает сообщение (я читаю из канала в while(1)).

Мой вопрос: не должна ли операция read также удалить сообщение из канала, чтобы оно больше не читалось? Разве не в этом суть принципа "первым пришел - первым вышел"? Это то, что мне нужно делать вручную?

Вот и мой код, если это поможет: http://pastebin.com/Ag7vgrav
Что я делаю писать в FIFO - это просто: echo test > /home/ubuntu/work/my_fifo


person Eduard Luca    schedule 21.04.2013    source источник


Ответы (1)


Вам нужно проверить код возврата от read(2). Если он возвращает -1, произошла ошибка, и вам следует немедленно прекратить чтение. Если он возвращает 0, это EOF, что означает, что писатель закрыл свой конец FIFO, и вы также должны прекратить запись и закрыть свой конец FIFO.

Для поддержки нескольких клиентов вам необходимо повторно открывать FIFO каждый раз, когда вы принимаете нового клиента.

У вас также есть неопределенное поведение в том, как вы управляете дочерним потоком. Нет гарантии, что поток запустится до конца текущей итерации цикла while в main(), после чего экземпляр thread_arg выходит за пределы области видимости. Чтобы гарантировать, что поток все еще может получить доступ к этим данным, пока они еще действительны, вам необходимо либо сделать их глобальными данными (если у вас есть только один дочерний поток), либо динамически распределить их в куче. Обычный шаблон для этого таков:

// Parent thread:
thread_arg *arg = malloc(sizeof(*arg));
...
pthread_create(..., &thread_proc, arg);

void *thread_proc(void *t_arg)
{
    thread_arg *arg = t_arg;

    // Thread code goes here
    ...
    free(arg);
    return exit_status;
}
person Adam Rosenfield    schedule 21.04.2013
comment
Ах я вижу. Перемещение open внутри петли помогло. По какой-то причине я сейчас ничего не могу записать в stdout, если только не exit или return, но отладка с использованием файлов пока подойдет. Мое приложение иногда давало сбой (ошибка сегментации), и я думаю, это связано с вашим вторым замечанием. Спасибо! - person Eduard Luca; 21.04.2013