canalizar strings mais longas para tr causa travamento e pico de CPU

canalizar strings mais longas para tr causa travamento e pico de CPU

Mac OS Yosemite (10.10.5). Eu sei que esta é a seção Unix/Linux... mas acho que esta questão provavelmente se encaixa melhor aqui do que no MacOS.

Meu terminal começou a travar na inicialização antes de mostrar um prompt... e o uso da CPU aumentou ao mesmo tempo. Posso CTRL-C e receber um prompt (presumivelmente saindo de algum .bashrc/.profile/etc suspenso/em execução).

Eu descobri rapidamente que certas linhas no meu .bashrc estavam causando o travamento. Isso é novo (ou seja, não mudei nada no meu .bashrc e tudo funcionava bem), então algo mudou no sistema.

Parece que certas strings mais longas resultam em pico de travamento/CPU.

Posso reproduzir isso canalizando uma corda tr -d '\n'e vendo se ela trava.

macattack:~ $ openssl rand -base64 93  | tr -d '\n'
eDsz4JqFX/HAVjplNI6WDWwPRp9l9snp6UKp/pLn+GbBvJx0+ZMvSJFS/SuCwjMRRXVXfUvBdkaH1R0UgCr2UOf283MvHVTRusLFEVPcGCIz1t3sFMU/3foRzNWVmattp@macattack:~ $ openssl rand -base64 94 | tr -d '\n'
^C
mattp@macattack:~ $ openssl rand -base64 94 | tr -du '\n'
^C

Parece que 93 caracteres é o número mágico onde tr começa a travar. O openssl não está travando (ou seja, se eu remover o tubo para que trtudo saia). No entanto, minha linha de problema original tinha comprimento diferente.

mattp@macattack:~ $ echo 'echo -e "$TS\t${TERM_SESSION_ID}\t$(pwd)\t$(history 1 | cut -c 8-)\n" >> $HOME/.history/history-$(date "+%Y-%m-%d")-${USER}.log;' | tr -d '\n'
^C-bash: echo: write error: Interrupted system call

mattp@macattack:~ $ echo 'echo -e "$TS\t${TERM_SESSION_ID}\t$(pwd)\t$(history 1 | cut -c 8-)\n" >> $HOME/.history/history-$(date "+%Y-%m-%d")-${USER}.log' | tr -d '\n'

mattp@macattack:~ $ echo 'echo -e "$TS\t${TERM_SESSION_ID}\t$(pwd)\t$(history 1 | cut -c 8-)\n" >> $HOME/.history/history-$(date "+%Y-%m-%d")-${USER}.log' | wc -c
     128
mattp@macattack:~ $

Este é provavelmente um problema de tubulação, e não um trproblema. Posso reproduzir o mesmo problema com sed(o comando não faz sentido... apenas ilustra o travamento).

mattp@macattack:~ $ echo 'echo -e "$TS\t${TERM_SESSION_ID}\t$(pwd)\t$(history 1 | cut -c 8-)\n" >> $HOME/.history/history-$(date "+%Y-%m-%d")-${USER}.log;'  | sed 's/\n/ /g'
^C-bash: echo: write error: Interrupted system call

mattp@macattack:~ $ echo 'echo -e "$TS\t${TERM_SESSION_ID}\t$(pwd)\t$(history 1 | cut -c 8-)\n" >> $HOME/.history/history-$(date "+%Y-%m-%d")-${USER}.log'  | sed 's/\n/ /g'
echo -e "$TS\t${TERM_SESSION_ID}\t$(pwd)\t$(history 1 | cut -c 8-)\n" >> $HOME/.history/history-$(date "+%Y-%m-%d")-${USER}.log
mattp@macattack:~

Fiquei sem ideias para solucionar isso.
Os comandos suspensos funcionam bem em um servidor Linux centos aleatório. Os comandos funcionavam bem no macOS até recentemente. Nunca encontrei canos pendurados antes. Achei que talvez fossem caracteres estranhos na entrada causando um problema ... mas a string aleatória do openssl mostra o contrário. Os ulimits são iguais aos de outro Mac que NÃO apresenta o mesmo problema.

mattp@macattack:~ $ ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
file size               (blocks, -f) unlimited
max locked memory       (kbytes, -l) unlimited
max memory size         (kbytes, -m) unlimited
open files                      (-n) 7168
pipe size            (512 bytes, -p) 1
stack size              (kbytes, -s) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 709
virtual memory          (kbytes, -v) unlimited

Usar dtrussparece trtravar na chamada read_nocancel.

Atualizar

Fazendo progresso. Encontrei um comentário sobre tamanhos de buffer de suspensão e tubo. Roubei um script de teste daqui: Qual é o tamanho do buffer do tubo?

A execução enquanto o problema está acontecendo mostra um buffer de canal de 128 bytes. Reinicialize (o problema desaparece temporariamente) e o buffer do pipe tem 65.536 bytes. Veja o resultado do teste abaixo.

Então agora a questão é: por que/como "algo" está reduzindo o tamanho do buffer do tubo no sistema.

Com problema

$ /bin/bash -c 'for p in {0..18}; do pipe-buffer-test.sh $((2 ** $p)) 0.5; done'
write size:          1; bytes successfully before error: 128
write size:          2; bytes successfully before error: 128
write size:          4; bytes successfully before error: 128
write size:          8; bytes successfully before error: 128
write size:         16; bytes successfully before error: 128
write size:         32; bytes successfully before error: 128
write size:         64; bytes successfully before error: 128
write size:        128; bytes successfully before error: 128
write size:        256; bytes successfully before error: 0
write size:        512; bytes successfully before error: 0
write size:       1024; bytes successfully before error: 0
write size:       2048; bytes successfully before error: 0
write size:       4096; bytes successfully before error: 0
write size:       8192; bytes successfully before error: 0
write size:      16384; bytes successfully before error: 0
write size:      32768; bytes successfully before error: 0
write size:      65536; bytes successfully before error: 0
write size:     131072; bytes successfully before error: 0
write size:     262144; bytes successfully before error: 0

Após a reinicialização (problema desaparecido temporariamente)

$ /bin/bash -c 'for p in {0..18}; do pipe-buffer-test.sh $((2 ** $p)) 0.5; done'
write size:          1; bytes successfully before error: 65536
write size:          2; bytes successfully before error: 65536
write size:          4; bytes successfully before error: 65536
write size:          8; bytes successfully before error: 65536
write size:         16; bytes successfully before error: 65536
write size:         32; bytes successfully before error: 65536
write size:         64; bytes successfully before error: 65536
write size:        128; bytes successfully before error: 65536
write size:        256; bytes successfully before error: 65536
write size:        512; bytes successfully before error: 65536
write size:       1024; bytes successfully before error: 65536
write size:       2048; bytes successfully before error: 65536
write size:       4096; bytes successfully before error: 65536
write size:       8192; bytes successfully before error: 65536
write size:      16384; bytes successfully before error: 65536
write size:      32768; bytes successfully before error: 65536
write size:      65536; bytes successfully before error: 65536
write size:     131072; bytes successfully before error: 0
write size:     262144; bytes successfully before error: 0

Responder1

Com base no comentário de @Barmar sobre vazamento de buffers de kernel, dei uma olhada nos kexts atuais que não são do sistema operacional. Percebi que havia um relativamente novo em uma instalação recente do BlockBlock (https://objective-see.com/products/blockblock.html).

Desinstalei o BlockBlock, reiniciei e o problema não voltou a ocorrer. Portanto, BlockBlock foi o culpado neste caso e relatei o problema ao autor.

No entanto, isso não é particularmente satisfatório, já que adotei uma abordagem principalmente de adivinhação e verificação para descobrir a causa e, para ser sincero, não entendo realmente a causa raiz (em termos de sistema operacional), o que significa que não sou o único -mais sábio para solucionar esse tipo de problema no futuro.

Se alguém se deparar com isso e puder explicar o que estava acontecendo com mais detalhes e fornecer uma abordagem para solução de problemas, seria uma resposta muito melhor do que "desinstalar o BlockBlock".

informação relacionada