Qu'est-ce qui fait mourir un processus Unix avec un tube cassé?

30

Voici quelques options auxquelles j'ai pensé, je ne sais pas laquelle est la bonne.

  1. Une erreur d'E / S s'est produite dans le tuyau.
  2. Le processus d'écriture à l'autre extrémité du tuyau est mort avec un échec.
  3. Tous les processus qui pouvaient écrire dans le tuyau l'ont fermé.
  4. Le tampon d'écriture du canal est plein.
  5. Le pair a fermé l'autre sens du tuyau duplex.
  6. L'écriture a échoué car il n'y a aucun processus pouvant lire à partir du canal.
  7. Un appel système a renvoyé l'erreur EPIPE et aucun gestionnaire d'erreur n'a été installé.
siamii
la source
Quelle est votre question? Demandez-vous laquelle est correcte ou s'il y a d'autres choses qui peuvent causer la rupture du tuyau?
EightBitTony
@EightBitTony Laquelle de ces réponses est correcte
siamii

Réponses:

38

Un processus reçoit un SIGPIPE lorsqu'il tente d'écrire sur un canal (nommé ou non) ou un socket de type SOCK_STREAM qui n'a plus de lecteur.

C'est généralement un comportement recherché. Un exemple typique est:

find . | head -n 1

Vous ne voulez findpas continuer à courir une fois headterminé (puis fermé le seul descripteur de fichier ouvert pour la lecture sur ce canal).

La yescommande s'appuie généralement sur ce signal pour se terminer.

yes | some-command

Écrira "y" jusqu'à ce que la commande some se termine.

Notez que ce n'est pas seulement quand les commandes se terminent, c'est quand tous les lecteurs ont fermé leur lecture fd au pipe. Dans:

yes | ( sleep 1; exec <&-; ps -fC yes)
      1 2       1        0

Il y aura 1 (le sous-shell), puis 2 (sous-shell + sommeil), puis 1 (sous-coque) puis 0 fd lecture du tuyau après que le sous-shell ferme explicitement son stdin, et c'est alors yesque recevra un SIGPIPE.

Ci-dessus, la plupart des shells utilisent un pipe(2)certain temps ksh93utilise un socketpair(2), mais le comportement est le même à cet égard.

Lorsqu'un processus ne tient pas compte du SIGPIPE, l'appel système d'écriture ( en général write, mais pourrait être pwrite, send, splice...) revient avec une EPIPEerreur. Ainsi, les processus souhaitant gérer manuellement le tuyau cassé ignoreraient généralement SIGPIPE et prendraient des mesures en cas d'erreur EPIPE.

Stéphane Chazelas
la source
14

(6)

L'écriture a échoué car il n'y a aucun processus pouvant lire à partir du canal.

Bien que, sauf si vous dupliquez des descripteurs et un fork, il ne peut y avoir qu'un seul processus pour commencer: généralement un canal a un lecteur et un écrivain, et lorsque l'un d'eux ferme la connexion, le canal est éteint. Si vous utilisez un canal nommé, vous pouvez établir plusieurs connexions (en série) avec lui, mais chacune représente un nouveau canal dans ce sens. Ainsi, un "canal" vers un thread ou un processus est synonyme d'un descripteur de fichier.

De man 7 pipe:

Si tous les descripteurs de fichiers se référant à l'extrémité lue d'un canal ont été fermés, alors une écriture (2) provoquera la génération d'un signal SIGPIPE pour le processus appelant. Si le processus appelant ignore ce signal, alors write (2) échoue avec l'erreur EPIPE.

Un "tuyau cassé" est donc pour l'écrivain ce que l'EOF est pour le lecteur.

boucle d'or
la source
0

Un tuyau cassé se produit lorsque le processus de lecture se termine avant le processus d'écriture. J'irais donc avec (6)

SidJ
la source
2
Il peut y avoir plusieurs processus de lecture ou d'écriture sur un canal, et le même processus peut être de lecture et d'écriture. De plus, il ne s'agit pas de quitter, il s'agit de fermer le descripteur de fichier.
Stéphane Chazelas