stdbuf supostamente comportamento para subprocessos

4

Eu não encontrei exatamente algo sobre o seguinte na página de manual . Como o suposto comportamento em subprocessos gerado por um processo que foi gerado por stdbuf ?

Por exemplo:

stdbuf -oL myprog

Do código , percebo que ele define LD_PRELOAD e, até onde eu sei, todas as variáveis de ambiente são herdadas em qualquer subprocesso.

Estou interessado nos subprocessos fork(); e fork(); execv(); . (Não tenho certeza se isso faria diferença.)

fork(); não deve alterar o comportamento. execv() usaria o mesmo LD_PRELOAD (assim como as configurações stdbuf que também são armazenadas em env) e, portanto, aplica o mesmo comportamento (do exemplo: stdout é line-buffered).

certo?

    
por Albert 29.04.2016 / 13:55

2 respostas

2

strace as chamadas do sistema execve (com environ) e write podem ajudar a ver o que está acontecendo:

Aqui com o stdbuf do GNU Coreutils 8.25. Eu acredito que o stdbuf do FreeBSD funciona da mesma forma:

exec e sem fork:

$ env -i strace -s200 -vfe execve,write /usr/bin/stdbuf -o0 /usr/bin/env /usr/bin/env > /dev/null
execve("/usr/bin/stdbuf", ["/usr/bin/stdbuf", "-o0", "/usr/bin/env", "/usr/bin/env"], []) = 0
execve("/usr/bin/env", ["/usr/bin/env", "/usr/bin/env"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so"]) = 0
execve("/usr/bin/env", ["/usr/bin/env"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so"]) = 0
write(1, "_STDBUF_O=0\n", 12)           = 12
write(1, "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so\n", 60) = 60
+++ exited with 0 +++

LD_PRELOAD e a configuração em _STDBUF_O é passada para os comandos env . As duas chamadas do sistema write() mesmo que a saída não vá para um terminal, confirma que a saída não está em buffer.

fork e exec:

$ env -i strace -s200 -vfe execve,write /usr/bin/stdbuf -o0 /bin/sh -c '/usr/bin/env; :' > /dev/null
execve("/usr/bin/stdbuf", ["/usr/bin/stdbuf", "-o0", "/bin/sh", "-c", "/usr/bin/env; :"], []) = 0
execve("/bin/sh", ["/bin/sh", "-c", "/usr/bin/env; :"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so"]) = 0
Process 16809 attached
[pid 16809] execve("/usr/bin/env", ["/usr/bin/env"], ["_STDBUF_O=0", "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so", "PWD=/home/stephane"]) = 0
[pid 16809] write(1, "_STDBUF_O=0\n", 12) = 12
[pid 16809] write(1, "LD_PRELOAD=/usr/lib/x86_64-linux-gnu/coreutils/libstdbuf.so\n", 60) = 60
[pid 16809] write(1, "PWD=/home/stephane\n", 19) = 19
[pid 16809] +++ exited with 0 +++
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_EXITED,

Mesma situação.

Portanto, sim stdbuf se aplica ao comando que ele executa e a todos os seus ancestrais (desde que não limpem seu ambiente como a libc faz para LD_PRELOAD para aplicativos setuid / setgid ...).

    
por 29.04.2016 / 18:12
1

O armazenamento em buffer é herdado por meio do fork / exec de timeout , conforme ilustrado pelo seguinte código de teste:

bash-4.1$ cat isbuffed.c 
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
int main(void)
{
    printf("should not appear if buffered");
    sleep(999);
    exit(EXIT_SUCCESS);
}
bash-4.1$ make isbuffed
cc     isbuffed.c   -o isbuffed
bash-4.1$ timeout 3 ./isbuffed
bash-4.1$ stdbuf -o0 timeout 3 ./isbuffed
should not appear if bufferedbash-4.1$ 
    
por 29.04.2016 / 17:49