signal - ¿Por qué este programa en C genera SIGPIPE más tarde de lo esperado?
sigint en c (4)
Este programa genera SIGPIPE
después de canalizarlo a " head -n 1
", después de un tiempo aleatorio. Entiendo que debido a que estamos alimentando más a " head -n 1
" después de la primera línea, esperaríamos que generara SIGPIPE
, pero en lugar de eso lo hará a un número aleatorio (generalmente> 20 y <200) antes de salir. ¿Alguna idea de por qué?
#include <stdio.h>
#include <stdlib.h>
main()
{
int i;
char *s = "ABCDEFGHIJKLMNOPQRSTUVWXYZ/n";
i = 0;
while (1) {
fputs(s, stdout);
fflush(stdout);
fprintf(stderr, "Iteration %d done/n", i);
i++;
}
}
Esto no es tarea, solo algo en las notas de mi profesor que no entiendo.
Creo que es simplemente porque las señales son asíncronas.
Actualización: como otros lo señalaron (más precisamente muchos, incluido SIGPIPE) no lo son. Esta fue una respuesta impensada :)
El comando head
utiliza stdio para leer stdin y, por lo tanto, el primer getc no vuelve hasta que el búfer está lleno o EOF, lo que ocurra primero.
Las escrituras de zócalos son almacenadas en búfer y asíncronas, por lo que generalmente no obtendrá un error que surja de una escritura específica hasta la siguiente lectura o escritura).
Son los caprichos de la programación.
Su productor, llamémoslo alphabeta
, puede correr por un período de tiempo antes de que la head
pueda leer y salir (rompiendo así la tubería).
Esa "cierta cantidad de tiempo", por supuesto, es variable.
A veces, alphabeta
ejecuta 20 veces antes de que head
pueda leer stdin y exit. A veces 200 veces. En mi sistema, a veces 300 o 1000 o 2000 veces. De hecho, teóricamente puede ajustarse a la capacidad de la tubería que conecta al productor y al consumidor.
Para la demostración, introduzcamos un poco de retraso para que podamos estar razonablemente seguros de que la head
está atascada en un read () antes de que alphabeta
produzca una sola línea de salida:
so$ { sleep 5; ./alphabeta; } | head -n 1
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Iteration 0 done
(NB no está garantizado que la alfabeta solo se repita una vez en la lista anterior. Sin embargo, en un sistema descargado , este es el caso más o menos siempre será así: la head
estará lista y su lectura / salida será más fácil. o-menos inmediatamente.)
En cambio, observa lo que sucede cuando retrasamos artificialmente la head
:
so$ ./alphabeta | { sleep 2; head -n 1; }
Iteration 0 done
...
Iteration 2415 done # <--- My system *pauses* here as pipe capacity is reached ...
Iteration 2416 done # <--- ... then it resumes as head completes its first read()
...
Iteration 2717 done # <--- pipe capacity reached again; head didn''t drain the pipe
ABCDEFGHIJKLMNOPQRSTUVWXYZ
Como nota aparte, @R .. tiene bastante razón en sus comentarios de que SIGPIPE es sincrónico. En su caso, la primera escritura inducida por fflush en una tubería rota (después de que el head
haya salido) generará sincrónicamente la señal. Esto es un comportamiento documentado .