Utiliser les signaux et le sigpipe

Je travaille sur une tâche qui implique l’écriture d’un programme pour traiter des données (calculer pi) à l’aide de fork (processus), des signaux et sélectionner.

Je suis en train de travailler sur les signaux et je pense que je veux utiliser SIGPIPE. Ainsi, si le programme le détecte, il essaie d’écrire à nouveau dans le canal (Si un processus tente d’écrire dans un canal sans lecteur , il sera envoyé le SIGPIPE).

J’utilise fork () dans main () pour atsortingbuer le même travail à chaque processus en les envoyant à la fonction worker.

void worker(int id) { .... (this piece of code is not relevant) if(write(pfd[id][1], &c, sizeof(c)) == -1) printf("Error occurred: %s\n",strerror(errno)); } 

Comment puis-je implémenter des signaux dans cette fonction pour attraper SIGPIPE et le faire écrire à nouveau dans le tuyau?

Je vous remercie!

Généralement, au lieu d’attraper SIGPIPE on l’ignore, ce qui entraîne l’échec de l’ write avec EPIPE au lieu de terminer le programme en silence.

Cependant: si vous obtenez un SIGPIPE lorsque vous écrivez dans un tube, n’essayez plus. Ça ne marchera jamais. SIGPIPE signifie que le tuyau n’a pas de lecteur – et si le tuyau n’a pas de lecteur maintenant, il n’aura jamais de lecteur. (Pensez-y de cette façon: comment un tuyau sans lecteur en obtiendrait-il un? C’est impossible!)

Votre problème est que vous fermez l’autre extrémité du tuyau. Corrigez cela et ne vous inquiétez pas pour SIGPIPE . SIGPIPE n’est que le symptôme.

Edit: Il y a deux questions à répondre ici. Si vous ne pouvez pas répondre à ces deux questions, ne vous occupez pas de SIGPIPE .

  1. Qu’est-ce qui ferait que mon programme reçoive SIGPIPE ? Le seul moyen de recevoir SIGPIPE est de fermer le bout de lecture. Cela se produit si le processus de lecture se bloque ou s’il est programmé pour fermer le tuyau. Si vous écrivez un serveur de réseau ou communiquez avec un processus inconnu, cela peut être courant. Toutefois, si vous écrivez les deux programmes, les deux s’exécutant localement, cela indique probablement une erreur de programmation.

  2. Que ferait mon programme quand il attrape SIGPIPE ? Si vous écrivez un processus client qui utilise un canal pour communiquer avec un serveur, qu’êtes-vous censé faire avec SIGPIPE ? Vous ne pouvez pas réessayer et les clients ne peuvent généralement pas redémarrer le serveur auquel ils sont connectés. Faites ce qui est raisonnable par défaut et laissez SIGPIPE terminer votre programme. Toutefois, si le serveur envoie des données à un client qu’il contrôle et obtient SIGPIPE , il peut redémarrer le client. Mais cela pourrait être une très mauvaise idée – par exemple, si le client est déterministe, il se plantera à nouveau et vous obtiendrez une boucle infinie plutôt qu’un simple crash.

Donc, la maxime générale est la suivante: ” Ne capturez que les erreurs que vous êtes prêt à gérer. ” Ne détectez pas les erreurs uniquement pour des raisons d’exhaustivité. Laissez-les simplement planter votre programme ou faire échouer l’opération et vous pourrez revenir en arrière et le déboguer plus tard.

Extrait de code: il s’agit d’un extrait de code provenant de l’un de mes projets. Si vous l’exécutez, SIGPIPE ne mettra pas fin à votre processus. Au lieu de cela, write générera une erreur EPIPE . Si vous écrivez un serveur de réseau, EPIPE est un moyen possible pour un client de se déconnecter subitement.

 void ignore_sigpipe(void) { struct sigaction act; int r; memset(&act, 0, sizeof(act)); act.sa_handler = SIG_IGN; act.sa_flags = SA_RESTART; r = sigaction(SIGPIPE, &act, NULL); if (r) err(1, "sigaction"); }