bash Прерванный системный вызов

Я получил сообщение "Прерванный системный вызов" и не знаю, почему честно. Моя домашняя работа - написать серверный скрипт, который использует fifo для связи с клиентским скриптом, в основном это работает, но я не знаю, как избавиться от этого сообщения. Буду признателен за любое предложение.

Мой серверный скрипт:

#!/bin/bash

server=serwerfifo

if [[ "$1" ]]; then
    if [[ ! -p $1 ]]; then
        echo "Reader(klient) not running"
    else
        echo $(expr $2 + $2) > $1 &
    fi
else
    trap "" SIGHUP SIGTERM SIGCHLD
    trap "exit 0" SIGUSR1

    if [[ ! -p $server ]]; then
        mkfifo $server
    fi

    while true
    do
        if read line < $server; then
            $0 $line &
        fi
    done
fi

Сообщение появляется, когда переводчик обогащает эту строку:

if read line < $server; then

2 ответа

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

while :; do # if we hit end-of-FIFO, then loop around and try to reopen
  while read -r line; do
    "$0" "$line" &
  done < "$server"
done

Обратите внимание, что < "$server" на петле, а не на read, так что если у вас есть несколько строк, написанных вашим писателем, эти несколько строк будут прочитаны читателем, прежде чем он закроет FIFO.


Другая важная вещь здесь - это использование фоновых процессов, делающих события асинхронными (и, следовательно, их упорядочение недетерминированным). Вы действительно можете получить полностью законно прерванный системный вызов, особенно когда у вас есть операции открытия и закрытия, выполняемые в трудные для прогнозирования времена: ядру UNIX разрешено сообщать пользователю, что ему нужно повторить попытку (и что другая попытка будет успешной)). Это не ошибка, это законный и допустимый результат.

(Заменяет предыдущие комментарии.)

Первый,

$0 $line & 

должно быть

"$0" "$server" "$line" &

потому что код производителя ожидает $1 быть именем ФИФО. Двойные кавычки на случай, если что-нибудь в $0, $server, или же $line включает пробелы или другие специальные (для bash) символы.

На cygwin я смог протестировать код вручную foo.sh в одном терминале и foo.sh serwerfifo 4 в отдельном терминале. Однако я не смог воспроизвести "прерванный системный вызов". Я, однако, получил бесконечный цикл удвоения значений в foo.sh Терминал. Это было намерение? Причина в том, что каждый вызов $0 ... & производит другую строку вывода для read потреблять, после чего потребительская сторона призывает $0 ... & снова производя еще одну строку вывода...

Другие вопросы по тегам