(Courriels de diversion: <presentez@orthographieraient-interviendrions.com> <abuserais@cingleront-desires.com> <pauperisons@renseignant-reelirions.com> <ressassait@ânonnent-necessaire.com> <humecterait@flouerais-illusionnes.com> <inversaient@contribuons-entravait.com> <racheterent@crasse-vissais.com> <confrontez@croquiez-deferente.com> <denicheras@petarader-predilections.com> <mi-voix@thesauriserais-absente.com> )


Le  5 Jan, Arnaud Rolly écrit :

>  switch(pid=fork())
>  {
>  	case -1:
>  		/* error */
>  		error_show("Impossible to launch the necessary program.");
>  	case 0:
>  		/* soon process */
>  		system(exec_command);

  Quand system retourne, le fils exécute le code qui suit : tu voulais
sans doute mettre un exit quelque part par ici pour terminer le fils.

>  	default:
>  		/* father process */
>  		signal(SIGCHLD,end_fork);

  Tu devrais installer le gestionnaire de signal _avant_ de faire le
fork : rien ne te garantit en effet que le séquence des événements ne
va pas être :
  - fils se termine ;
  - père installe le gestionnaire.

>  Le problème, c'est que lorsque je ferme le programme lancé avec le system(...),
>  tout plante en bautée, avec en prime un message X :
>  Xlib: unexpected async reply (sequence 0x1598)!
>  FIN!

  Comme FIN! s'affiche, les choses se passent dans le bon ordre.

  Ton problème est caractéristique d'un double accès au serveur X sur
la même connexion. Comme il te manque un exit dans le fils, tu dois
exécuter le code que tu aurais voulu limiter au père, en particulier le
code d'interaction avec l'utilisateur.

  C'est là qu'il faut se rappeler qu'après le fork, le canal de
communication avec le serveur X est partagé entre le père et le fils.
Ils se retrouvent en conccurrence pour lq lecture de ce qu'envoie le
serveur, et sont susceptibles de mêler ce qu'ils lui envoient. Pas top.

>  Le man de signal me donne :
>  void (*signal(int signum, void (*handler)(int)))(int);
>  Heu... Je suis pas sur de l'utilisation que j'en ai faite.

  Pour signal, c'est bien.

  Comme tu as l'air de te moquer du code de retour du programme lancé,
tu as une autre technique pour éviter les zombies : il te suffit
d'utiliser le mécanisme de gestion des orphelins du sytème (que j'ai
évoqué dans un courrier précédent).

  L'idée est de faire un fork, puis dans le fils de faire un autre fork.
Le fils n'attend pas le petit fils (qui se retrouve orphelin et est
donc adopté par le processus de pid 1). Le père fait un wait, qui ne
bloque pas longtemps puisque le fils meurt de suite. 0 zombie, donc,
puisque tous les morts sont attendus.

  Enfin, il faut se souvenir que la fonction system intervient aussi
là-dedans : pour ce qui nous intéresse, on peut schématiser son code
comme suit :

  int system(const char *cmd) {
    int wstatus;
    switch (fork() {
    case 0:
      execl("/bin/sh", "/bin/sh", "-c", cmd, NULL);
      return -1;
    case -1:
      return -1;
    default:
      wait(&status);
      return status;
    }
  }

-- 
Marc Thirion              | Toulouse, France
Un Travail pour Chacun    : http://www.multimania.com/untravailchacun/
Marc.Thirion@ISOscope.com : http://www.ISOscope.com/Pérennité des logiciels et des systèmes



---------------------------------------------------------------------
Aide sur la liste: <URL:mailto:linux-31-help@savage.iut-blagnac.fr>Le CULTe sur le web: <URL:http://savage.iut-blagnac.fr/>