¿Bajo qué condición un subproceso Python obtiene un SIGPIPE?

Estoy leyendo la documentación de Python en la clase de Popen en la sección del módulo de subproceso y encontré el siguiente código:

p1 = Popen(["dmesg"], stdout=PIPE) p2 = Popen(["grep", "hda"], stdin=p1.stdout, stdout=PIPE) p1.stdout.close() # Allow p1 to receive a SIGPIPE if p2 exits. output = p2.communicate()[0] 

La documentación también establece que

“La llamada p1.stdout.close () después de iniciar p2 es importante para que p1 reciba un SIGPIPE si p2 sale antes de p1.

¿Por qué se debe cerrar p1.stdout antes de que podamos recibir un SIGPIPE y cómo p1 sabe que p2 sale antes de p1 si ya lo hemos cerrado?

SIGPIPE es una señal que se enviaría si dmesg intentara escribir en un conducto cerrado. Aquí, dmesg termina con dos destinos para escribir, su proceso Python y el proceso grep .

Esto se debe a que el archivo de clones de subprocess se maneja (mediante la función os.dup2() ). La configuración de p2 para usar p1.stdout desencadena una llamada os.dup2() que solicita al sistema operativo que duplique el p1.stdout os.dup2() tubería; el duplicado se utiliza para conectar dmesg a grep .

Con dos manejadores de archivo abiertos para dmesg stdout, a dmesg nunca se le da una señal SIGPIPE si solo uno de ellos se cierra antes, por lo que el cierre de grep nunca se detectaría. dmesg seguiría produciendo innecesariamente.

Entonces, al cerrar p1.stdout inmediatamente, se asegura de que la única lectura de dmesg restante de dmesg stdout sea el proceso grep , y si ese proceso fuera a salir, dmesg recibe un SIGPIPE .