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 ... &
снова производя еще одну строку вывода...