Compreendendo o comportamento de subshell e stdout com pipe

2

Digamos que eu tenha o arquivo .c e o executável correspondente (digamos foo) que recebe alguma entrada de stdin e faça uma chamada sys para /bin/sh . Alimentando entrada para este executável como segue:

python -c "<some script to feed input>" | ./foo

Eu observei que o shell chamado por foo se fecha imediatamente e foo termina. No entanto, alguém no IRC recomendou que a execução fosse assim:

(python -c "<some script to feed input>"; cat) | ./foo

mantém o subshell invocado por ./foo ainda em execução. Eu gostaria de saber o que está acontecendo aqui.

Minha Especulação: No primeiro caso, o stdout do script python fecha assim que é feito, enviando EOF para o stdin do processo ./foo terminando ./foo ? Mas isso não faz sentido para mim, pois a chamada sys deve ser um bloqueador, levando a ./foo a não terminar. Eu apreciaria a ajuda e um ponteiro para recursos para corrigir o entendimento errôneo. Obrigado!

    
por iart 09.06.2014 / 01:54

1 resposta

3

Não existe algo como “enviar EOF”. O fim do arquivo é atingido quando não há mais dados para ler.

No primeiro trecho, assim que o script Python sair, não haverá mais processo que tenha o canal aberto para gravação. Portanto, uma vez que foo tenha terminado de ler todos os dados que foram enviados no pipe, ele detecta uma condição de fim de arquivo em sua entrada padrão.

No segundo trecho, assim que o script Python sai, o pipe ainda é aberto pela subshell. Portanto, mesmo se foo terminar de ler todos os dados produzidos pelo script Python, ele continuará esperando por mais entradas. O subshell lança cat , que lê e encaminha dados de sua própria entrada padrão. Quando cat sai, a situação é a mesma de antes: não há mais processo que tenha o canal aberto para gravação e foo atingirá o final de sua entrada.

Quando um processo é bloqueado em uma chamada de sistema read , há vários motivos pelos quais a chamada do sistema pode retornar:

  • Se os dados estiverem disponíveis, read retornará um valor positivo e armazenará muitos bytes no buffer passados para ele.
  • Se o final do arquivo for atingido, read retornará 0. Para um arquivo normal, isso acontece quando a posição do arquivo atinge o final do arquivo. Para um pipe, isso acontece quando o último processo que tinha o arquivo aberto morre e o buffer do pipe foi totalmente consumido.
  • Se algum erro ocorrer, read retornará -1.
por 09.06.2014 / 02:09