¿Qué distribución de probabilidad modela esta condición de carrera?

10

Considere el siguiente comando: bash -c "echo x; cat 1" | tee 1.

Tengo entendido que se bifurcaría a un nuevo shell, escribiría xen stdout, escribiría file 1 not founden stderr, saldría y devolvería el control al proceso padre, y escribiría xen stdout y to 1. Por lo tanto, esperaría que el resultado final fuera x, y el archivo 1contiene exactamente la cadena x.

Sin embargo, éste no es el caso. En realidad, el archivo 1generalmente contiene al menos dos instancias xy, a veces, miles de líneas de xs. En una prueba por lotes de ejecutar el comando diez mil veces, el número medio de xs escritos en el archivo fue 52.3, y la mediana fue 1. ¿Qué mecánico está causando esto? ¿Qué distribución de probabilidad modela este comportamiento? Sospecho que es condicionalmente geométrico y por lo demás uniforme.

Will Sherwood
fuente
3
Tiene que ver con el momento de la ejecución del lado izquierdo y derecho de la tubería. Ambos se inician simultáneamente o cerca de él. Si teeha abierto el archivo para escribir antes de abrirlo catpara leer, puede obtener muchos x-es en el archivo. En ese caso, el "ciclo" terminaría siempre que las catlecturas fueran más rápidas que las teeescrituras, llegando al final del archivo.
Kusalananda
De las pruebas limitadas aquí, el número promedio de xs escritos en el archivo fue de 4.35. Supongo que dependerá mucho de la carga de la máquina.
Renan

Respuestas:

1

Esta es muy curiosa, así que traté de investigarla con la ayuda de strace. Ejecutó su comando en un bucle 1000 veces:

mkdir {000..999}
for i in {000..999}; do
echo $i
(cd $i; strace -f -o trace.log bash -c 'bash -c "echo x; cat 1" | tee 1 >/dev/null'; )
done

Encontré el archivo con la mayoría de las líneas ( wc -l */1 | sort -nr | head -n2) y verificó el correspondiente trace.log. Ciertamente puedo ver muchos:

7567  <... read resumed> "x\n", 8192)   = 2
7567  write(1, "x\n", 2)                = 2
7567  write(3, "x\n", 2)                = 2
7567  read(0,  <unfinished ...>
7568  read(3, "x\n", 131072)            = 2
7568  write(1, "x\n", 2)                = 2
7567  <... read resumed> "x\n", 8192)   = 2
7567  write(1, "x\n", 2)                = 2
7567  write(3, "x\n", 2)                = 2
7567  read(0,  <unfinished ...>
7568  read(3, "x\n", 131072)            = 2
7568  write(1, "x\n", 2)                = 2
7567  <... read resumed> "x\n", 8192)   = 2
7567  write(1, "x\n", 2)                = 2
7567  write(3, "x\n", 2)                = 2
7567  read(0,  <unfinished ...>

Donde 7567 es tee 1y 7568 es cat 1. Los dos definitivamente se alternan, así que sí, como se sospecha, se trata del momento de la ejecución (e imagino el cambio de contexto) de los dos comandos.

chutz
fuente