conectar cadenas más largas a tr provoca bloqueos y picos de CPU

conectar cadenas más largas a tr provoca bloqueos y picos de CPU

MacOS Yosemite (10.10.5). Sé que esta es la sección Unix/Linux... pero supongo que esta pregunta probablemente encaje mejor aquí que en MacOS.

Mi terminal comenzó a colgarse al iniciar antes de mostrar un mensaje... y el uso de la CPU aumentó al mismo tiempo. Puedo presionar CTRL-C y luego recibir un mensaje (presumiblemente saliendo de algún archivo .bashrc/.profile/etc que está colgado/en ejecución).

Rápidamente descubrí que ciertas líneas en mi .bashrc estaban causando el bloqueo. Esto es nuevo (es decir, no cambié nada en mi .bashrc y todo solía funcionar bien), por lo que algo cambió en el sistema.

Parece que conectar ciertas cadenas más largas provoca un bloqueo o un pico de CPU.

Puedo reproducir esto colocando una cuerda tr -d '\n'y viendo si cuelga.

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 es el número mágico donde tr comienza a colgarse. openssl no se bloquea (es decir, si quito la tubería para que trtodo salga). Sin embargo, la línea de mi problema original resultó tener una longitud 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:~ $

Probablemente se trate de un problema de tubería más que de un trproblema. Puedo reproducir el mismo problema con sed(el comando no tiene sentido... solo ilustra el bloqueo).

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:~

Me he quedado sin ideas para solucionar este problema.
Los comandos para colgar funcionan bien en un servidor Linux centos aleatorio. Los comandos funcionaron bien en macos hasta hace poco. Nunca antes me había topado con tuberías colgadas. Pensé que tal vez eran caracteres extraños en la entrada los que causaban el problema... pero la cadena aleatoria de openssl muestra lo contrario. Los ulimits son los mismos que en otra Mac que NO tiene el mismo 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

Usarlo parece bloquearse en la llamada read_nocancel dtruss.tr

Actualizar

Haciendo progreso. Encontré un comentario sobre los tamaños de amortiguadores para colgar y tuberías. Robé un script de prueba desde aquí: ¿Qué tamaño tiene el amortiguador de tubería?

La ejecución mientras ocurre el problema muestra un búfer de canalización de 128 bytes. Reinicie (el problema desaparece temporalmente) y el búfer de canalización es de 65536 bytes. Vea el resultado de la prueba a continuación.

Entonces ahora la pregunta es, ¿por qué/cómo "algo" está reduciendo el tamaño del búfer de tubería en el sistema?

con 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

Después de reiniciar (el problema desapareció temporalmente)

$ /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

Respuesta1

Basado en el comentario de @Barmar sobre la fuga de buffers del kernel, eché un vistazo a los kexts actuales que no son del sistema operativo. Me di cuenta de que había uno relativamente nuevo debido a una instalación reciente de BlockBlock (https://objective-see.com/products/blockblock.html).

Desinstalé BlockBlock, reinicié y el problema no volvió a ocurrir. Entonces BlockBlock fue el culpable en este caso y le informé del problema al autor.

Sin embargo, esto no es particularmente satisfactorio ya que adopté un enfoque principalmente de adivinar y verificar para descubrir la causa y, para ser honesto, realmente no entiendo la causa raíz (en términos del sistema operativo), lo que significa que no soy el -Más sabio para solucionar este tipo de problemas en el futuro.

Si alguien se encuentra con esto y puede explicar lo que sucedió con más detalle y brindar un método de solución de problemas, sería una respuesta mucho mejor que "desinstalar BlockBlock".

información relacionada