É apenas que quando o stdout não é um terminal, a saída é armazenada em buffer.
E quando você pressiona Ctrl-C , esse buffer é perdido como / se ainda não foi escrito.
Você obtém o mesmo comportamento com qualquer coisa usando stdio
. Tente por exemplo:
grep . > file
Insira algumas linhas não vazias e pressione Ctrl-C , e você verá que o arquivo está vazio.
Por outro lado, digite:
xinput test 10 > file
Digite o suficiente no teclado para que o buffer fique cheio (pelo menos 4k de saída), e você verá o tamanho do arquivo crescer em pedaços de 4k de cada vez.
Com grep
, você pode digitar Ctrl-D para que grep
seja encerrado normalmente após ter liberado seu buffer. Para xinput
, não acho que exista essa opção.
Observe que, por padrão, stderr
não é armazenado em buffer, o que explica por que você tem um comportamento diferente com fprintf(stderr)
Se, em xinput.c
, você adicionar um signal(SIGINT, exit)
, que diga xinput
para sair normalmente quando receber SIGINT
, verá que file
não está mais vazio (supondo que não Não travar, pois chamar funções de biblioteca de manipuladores de sinais não é garantido como seguro: considere o que poderia acontecer se o sinal chegasse enquanto o printf estivesse gravando no buffer).
Se estiver disponível, você pode usar o comando stdbuf
para alterar o comportamento do buffer stdio
:
stdbuf -oL xinput test 10 > file
Existem muitas perguntas neste site que abrangem a desativação do tipo stdio buffering, onde você encontrará soluções ainda mais alternativas.