2016-05-23 6 views
1

Dans mon programme, je reçois un gel parfois lors de l'écriture sur stderr dans ce cas:gel lors de l'écriture `stderr`

  1. programme commence (par exemple du terminal)
  2. fourches programme lui-même deux fois et en utilisant execvp pour démarrer chaque processus avec différents paramètres (le fichier d'origine est lu à partir de /proc/self/exe)
  3. Le premier programme démarré se ferme.
  4. Maintenant, les deux processus fourchus sont encore en cours d'exécution
  5. Fermer le terminal du premier programme a été lancé
  6. Quelques tentatives en utilisant fprintf d'écrire à stderr travail, sur un point que je vais obtenir un blocage complet sur mon programme. Le débogueur me dit son fprintf.

Que se passe-t-il ici? Ce que j'ai déjà essayé est de mettre un SIG_IGN sur SIGPIPE pour empêcher le programme de se bloquer dès que plus personne n'écoute sur les tuyaux. Mais maintenant je suis coincé (le comportement avec le gel est le même, avec SIG_IGN et sans elle).

Toute aide est appréciée.

+2

_Questions cherchant l'aide de débogage ("pourquoi ce code ne fonctionne-t-il pas?") Doit inclure le comportement souhaité, un problème ou une erreur spécifique et le code le plus court nécessaire pour le reproduire dans la question elle-même. Les questions sans énoncé de problème clair ne sont pas utiles aux autres lecteurs. Voir: Comment créer un exemple minimal, complet et vérifiable._ –

+0

La question a déjà reçu une réponse. – Nidhoegger

+0

Droit, mais encore, il devrait être utile aux futurs lecteurs. Explication est requise, à mon humble avis. –

Répondre

3

En bref: Le système envoie vos signaux de programme pour vous éviter un problème. Vous ignorez ces signaux. De mauvaises choses arrivent. Lors de l'exécution de votre programme parent, stdin (fd 0), stdout (fd 1) et stderr (fd 2) étaient connectés au TTY du shell qui vous servait (le terminal). Ceux-ci fonctionnent beaucoup comme des tuyaux. Lorsque vous avez fermé le terminal, ces fds restent suspendus, et personne de l'autre côté ne peut communiquer avec eux.

Au début, rien ne se passe mal. Vous écrivez à stderr, et la bibliothèque standard met en cache ces écritures. Aucun appel système n'est effectué, donc pas de problème.

Mais alors les tampons se remplissent, et stdlib essaie de les vider. Quand il fait cela, il remplit les tampons du noyau pour le tuyau ou ATS. Au début, cela fonctionne bien aussi. Tôt ou tard, cependant, ces tampons se remplissent aussi bien. Quand cela arrive, le noyau suspend vos processus et attend que quelqu'un lise l'autre bout de ces tuyaux. Depuis que vous avez fermé le terminal, personne ne le fera jamais, et vos programmes sont suspendus indéfiniment.

La manière standard d'éviter ce problème consiste à déconnecter les descripteurs de fichier 0-2 du TTY de contrôle. Au lieu de vous dire comment faire cela, je voudrais suggérer que ce que vous essayez de faire ici, exécuter un programme afin qu'il soit complètement déconnecté d'un ATS, a un nom: démoniser.

Consultez la question this pour plus de détails sur la façon de procéder.

Edité à ajouter:

Il n'a pas été clairement votre fonction si les programmes que vous execve ING sont vos propres ou non. Si ce n'est pas le cas, sachez que de nombreux programmes utilisateur ne sont pas conçus pour fonctionner en tant que démon. La mise en garde la plus évidente est que si un programme non connecté à un TTY ouvre un fichier TTY, et à moins qu'il ne passe O_NOCTTY à open, ce TTY devient le TTY de contrôle du programme. Selon les circonstances, cela peut entraîner des résultats inattendus.

+0

Merci beaucoup, cette explication m'a beaucoup aidé. Ce que je voulais faire de toute façon, c'est consigner dans un fichier. La sortie de connexion au terminal est temporaire pendant le développement. Je suppose que c'est un signe maintenant pour que le programme se connecte à un fichier à la place :). Merci beaucoup! – Nidhoegger

+0

@Nidhoegger, si vous écrivez dans un fichier avec 'fprintf (stderr, ...)', soyez conscient de la sémantique. Si les fonctions stdio voient que la destination n'est pas un TTY, elles seront vidées lorsque les tampons internes sont pleins, et non lorsqu'elles voient un EOL ('\ n'). Selon votre cas, cela peut être ou ne pas être ce que vous voulez. –

+0

* Vous écrivez dans stderr, et la bibliothèque standard met ces écritures en cache. * Pas nécessairement. 'stderr' est normalement complètement unbuffered. Attacher 'strace' au processus en cours montrerait presque certainement les appels système étant faits à fd 2. –