No caminho até a minha casa, pensando na influência da chamada fflush(stdout) e na definição da chamada de sistema fork() - cria uma cópia idêntica do processo... -, chequei a conclusão de que o que estava acontecendo era que o fork() duplicava também os buffers do processo, entre eles, é claro, o buffer de saída (stdout). A questão era que alguns processos-filho estavam recebendo caracteres "x" nos buffers que herdavam de seus pais.
Encontrada uma resposta lógica, o problema passou a ser: como provar esta teoria através de um exemplo prático e real.
A prova
Para facilitar o entendimento do que estava ocorrendo com o programa do laço de chamadas fork() (Figura 3), em vez de imprimir caracteres "x", fica mais interessante imprimir um número correspondente à iteração do laço. Esta modificação gera o programa da Figura 5.
#include <stdio.h>
#include <unistd.h>
int main()
{
int i;
for (i=0; i<2; ++i) {
fork();
printf("%d",i);
}
return(0);
}
Figura 5 - Exemplo de código-fonte do laço de chamadas fork() imprimindo o número da iteração
No caso da Figura 5, o resultado esperado deveria ser "010111", mas obtém-se "01010101" devido a duplicação dos buffers de saída. A Figura 6 apresenta um fluxograma do que ocorre ao longo da execução do código da Figura 5. Ao final da execução, ter-se-á 4 processos executando. Como mostra a figura, após cada fork(), o conteúdo do buffer de saída stdout é duplicado no processo filho, o que significa que o processo filho recebe neste buffer o que o seu processo-pai havia mandado imprimir via printf().

Figura 6 - Fluxograma da execução do programa da Figura 5
Há, no entanto, uma forma mais simples de comprovar o comportamento da chamada fork() em relação a situação descrita neste artigo. Este é o caso do programa da Figura 7. Neste código, depois de imprimir um caractere "x", executa-se uma chamada fork() e em seguida imprime-se um caractere "y". O resultado esperado deveria ser "xyy". No entanto, em função da duplicação do buffer de saída na chamada fork(), o resultado será "xyxy".
#include <stdio.h>
#include <unistd.h>
int main()
{
printf("x");
fork();
printf("y");
return(0);
}
Figura 7 - Teste final