2008-09-19 79 views
5

Lorsque vous effectuez deux processus et que vous tuez celui à la "sortie" du tuyau, le premier processus recevait le signal "Broken Pipe", qui le terminait généralement aussi. Par exemple. en cours d'exécutionUn tuyau brisé ne termine plus les programmes?

$> do_something_intensive | less 

puis sortie moins utilisé pour vous retourner immédiatement à une coquille souple, sur un SuSE8 ou anciens communiqués. quand j'essaie cela aujourd'hui, do_something_intensive est évidemment encore en cours d'exécution jusqu'à ce que je le tue manuellement. Il semble que quelque chose a changé (glib? Shell?) Qui fait ignorer les "tuyaux cassés" du programme ...

Quelqu'un d'entre vous a des allusions à ce sujet? comment restaurer le comportement précédent? pourquoi cela a-t-il été changé (ou pourquoi cela a toujours existé plusieurs sémantiques)?

modifier: d'autres tests (en utilisant strace) révèlent que "SIGPIPE" est généré, mais que le programme ne soit pas interrompu. Un simple

#include <stdio.h> 
int main() 
{ 
    while(1) printf("dumb test\n"); 
    exit(0); 
} 

ira avec une infinie

--- SIGPIPE (Broken pipe) @ 0 (0) --- 
write(1, "dumb test\ndumb test\ndumb test\ndu"..., 1024) = -1 EPIPE (Broken pipe) 

quand moins est tué. Je pouvais pour le programme que d'un gestionnaire de signal dans mon programme et assurez-vous qu'il se termine, mais je suis plus à la recherche d'une variable d'environnement ou une option shell qui forcerait les programmes de mettre fin à SIGPIPE

modifier à nouveau: il semble être un problème spécifique à tcsh (bash le gère correctement) et dépendant du terminal (Eterm 0.9.4)

+0

Il serait utile de savoir ce shell que vous utilisez, et plus de détails sur ce que do_something_intensive fait en réalité. Aussi, que voulez-vous dire par "évidemment toujours en cours"? Est-ce qu'il apparaît dans une liste ps, ou est-ce que le shell ne répond pas? N'hésitez pas à éditer votre question avec plus de détails! – ehdr

+0

il apparaît dans une liste PS, le sheel ne répond pas jusqu'à ce que je tue toute la chaîne avec CTRL + C et l'utilisation du processeur devient élevée dans gkrellm. le shell utilisé est tcsh, comme cela est mentionné dans la question plus détaillée. Merci pour votre commentaire. – PypeBros

Répondre

0

Merci pour vos conseils, la solution se rapproche ...

Selon la page de manuel de tcsh, « coquilles non-connexion héritent Terminate le comportement de leurs parents. D'autres signaux ont les valeurs que la coquille hérita de son parent. "

Qui suggèrent que mon terminal est en fait la racine du problème ... s'il ignorait SIGPIPE, le shell lui-même ignorerait SIGPIPE aussi bien ...

modifier: avoir la confirmation définitive que le problème se pose uniquement avec Eterm + tcsh et a trouvé un signal soupçonneux manquant (SIGPIPE, SIG_DFL) dans le code source Eterm. Je pense que cela ferme l'affaire.

+0

Je me souviens depuis longtemps que quitter un shell csh avec des jobs backgrouynd permettait aux jobs de continuer à fonctionner, mais quitter un shell bash (ksh) tuerait tous les jobs non-nohup-ed. – dsm

+0

eterm/Eterm> svn diff Index: src/command.c ================================== ================================= --- src/command.c (révision 40503) +++ src/command.c (copie de travail) @@ -2304,6 +2304,7 @@ le signal (SIGILL, SIG_DFL); Signal (SIGSYS, SIG_DFL); Signal (SIGALRM, SIG_DFL); + signal (SIGPIPE, SIG_DFL); #ifdef SIGTSTP signal (SIGTSTP, SIG_IGN); Signal (SIGTTIN, SIG_IGN); – PypeBros

8

Eh bien, s'il y a une tentative d'écriture dans un canal après le départ du lecteur, un signal SIGPIPE est généré . L'application a la capacité d'attraper ce signal, mais si ce n'est pas le cas, le processus est détruit.

Le SIGPIPE ne sera pas généré avant que le processus appelant ne tente d'écrire, donc s'il n'y a plus de sortie, il ne sera pas généré.

2

Est-ce que "faire quelque chose d'intensif" a changé du tout? Comme Daniel l'a mentionné, SIGPIPE n'est pas un signal magique «votre tuyau est parti», mais plutôt un signal «essayez bien, vous ne pouvez plus lire/écrire ce tuyau».

Si vous avez le contrôle de "faire quelque chose d'intensif", vous pouvez le modifier pour écrire une sortie "indicateur de progression" pendant qu'il tourne. Cela soulèverait le SIGPIPE en temps opportun.

+0

à propos de do_something_intensive: si je fais "yes | less" et que je termine "less", "yes" reçoit un SIGPIPE et se termine. si à la place je fais "objdump -drS ... | less", "objdump" continue (malgré la présence de SIGPIPE); il en est de même d'une boucle muette faisant "printf". – PypeBros