Por que stdout não flush quando redirecionando a entrada de um fifo?

2

Eu tenho um programa que exibe uma mensagem de aviso e aguarda o usuário inserir algum texto.

$ program
Input a line of text: <aaaa>
Some more output.
$

Agora, também quero poder fornecer essa entrada, programaticamente, por meio de um FIFO, da seguinte forma:

$ program < fifo

Mas o que está acontecendo é que o prompt no stdout não aparece até que eu tenha fornecido a entrada para fifo .

Em seguida, tentei um equivalente muito simples do meu programa, da seguinte forma:

$ echo aaaa < fifo

Mesmo aqui, aaaa não aparece até que fifo tenha recebido sua entrada.

Pergunta: Como faço minha saída até o momento em que eu espero pela entrada de stdin aparecer em stdout ao usar FIFO?

    
por Harry 14.06.2018 / 15:39

1 resposta

4

O FIFO é aberto pelo shell, mas a abertura dele é bloqueada até que o FIFO seja aberto para gravação por algum outro processo. Como os redirecionamentos são processados antes da execução do comando, o programa nem é executado até que a chamada open() do shell retorne. Este é um comportamento documentado para a função de biblioteca open() C (usada pelo shell):

O_NONBLOCK

When opening a FIFO with O_RDONLY or O_WRONLY set:

  • If O_NONBLOCK is set, an open() for reading-only shall return without delay. An open() for writing-only shall return an error if no process currently has the file open for reading.

  • If O_NONBLOCK is clear, an open() for reading-only shall block the calling thread until a thread opens the file for writing. An open() for writing-only shall block the calling thread until a thread opens the file for reading.

Portanto, o shell obviamente não está usando O_NONBLOCK quando está abrindo o FIFO.

Solução:

  1. cat fifo | program

    cat lê do FIFO até o final do arquivo e sai.

  2. tail -f fifo | program

    tail lê a partir do FIFO até o final do arquivo e, em seguida, fica aguardando por mais até ser finalizado.

Qual destes é o mais adequado para a sua situação depende um pouco do que está escrevendo para o FIFO no outro lado, e como ele faz a escrita.

Terceira solução envolve a abertura do programa FIFO quando necessário.

De acordo com a seção Rationale em sh , um shell deve definir o padrão entrada para bloquear porque ...

If the shell did not reset this flag, it would immediately terminate because no input data would be available yet and that would be considered the same as end-of-file.

    
por 14.06.2018 / 16:43