Deixando read
timeout
read
timeout realmente funciona. O problema aqui é que a abertura de um FIFO em blocos de modo de leitura até o FIFO é aberto no modo de escrita. E nesse caso, isso não é read
que está bloqueado, isso é bash
, ao redirecionar seu FIFO para stdin.
Quando algum outro processo abrir o FIFO para gravação, bash
abrirá com sucesso o FIFO para leitura e executará o comando read
(que terminará como esperado).
Se você estiver usando o Linux, a página man do fifo nos diz que " abrir um FIFO para leitura e gravação terá sucesso tanto no modo de bloqueio quanto de não bloqueio ". Portanto, o seguinte comando irá expirar mesmo quando nenhum outro processo abrir o FIFO para gravação:
read -st 1 data <> "$fifo"
Cuidado com a condição da corrida
Uma vez que o seu processo shell abra o FIFO para leitura, o (s) gravador (es) serão desbloqueados e, quando bash
redirecionar o FIFO para stdin e chamar read
, o gravador poderá abrir o FIFO e escreva várias vezes . Como você lê apenas uma linha por vez, qualquer linha remanescente a ser lida enquanto a FIFO é fechada nas duas extremidades será perdida. Uma solução melhor seria manter o FIFO aberto, redirecionando-o para stdin para todo o loop while
... done
, como você fez para o fd 3. Algo como:
while ...; do
...
read -st 1 data
...
done 3<"$lock" < "$fifo"
Ou mesmo em um nível superior, se você tiver vários leitores em paralelo. O que importa é manter o FIFO aberto. O mesmo para o lado do escritor.
Por exemplo, com o código que você publicou com sua atualização, o nível superior seria:
# Writer
writer > "$myfifo" &
# Reader
for i in $(seq 1 10); do
reader $i &
sleep 1
done < "$myfifo"
Claro, remova os redirecionamentos para / de $myfifo
em qualquer outro lugar no seu código, e remova o echo "$(date -R) writing \"$i\"."
no seu gravador, ou redirecione-o para stderr, senão ele irá para o FIFO.