oliparcol Murphy's Law Master | Bonjour,
Je suis en train de faire un petit shell. J'utilise pour cela un fork et la fonction execvp pour exécuter le programme. Lorsque mon programme est en cours d'exécution, mon shell est bloqué en attente du signal SIGCHLD (envoyé par son enfant). Je gère cette arrivée de signal à l'aide d'un traitant qui fait un loop grâce à des wait non bloquants (utile dans le cas où on a un pipe et plusieurs applis qui terminent en même temps et donc la possibilité de recevoir un seul SIGCHLD pour plusieurs morts).
Voici mon problème:
Je me mets en pause pour attendre le signal SIGCHLD qui va débloquer mon shell (le père). Le problème est que sur des pc modernes, la mise en pause, est plus longue que l'execution de certains programmes (genre ls) et donc le shell reçoit le signal SIGCHLD avant sa mise en pause. Il traite ce signal (donc le fils ne devient pas un zombie) mais malheureusement, le shell attend indéfiniment un signal permettant de le sortie du mode pause.
Est-ce qu'il y a moyen de résoudre ce problème ? La seule technique que j'ai trouvée est de faire un sleep avant le lancement de mon programme (donc vraiment pas une solution ).
Voici le code du traitant du signal SIGCHILD.
Code :
- void traitement_signaux_fin(int sig_id){
- 39 /* apparemment, si deux signaux SIGCHLD
- 40 * arrivent prèsque simultanément, le
- 41 * système en enverra qu'un au shell
- 42 * il faut donc libérer tous les
- 43 * programmes zombies avec un
- 44 * wait non bloquant
- 45 */
- 46 sig_id = 1;
- 47 while (waitpid (-1, NULL, WNOHANG) != -1);
- 48
- 49
- 50 }
|
Voici le code de la partie fork() + attente: (il y a aussi une gestion de la redirection dans le cas d'un pipe)
Code :
- 83 id_fils = fork();
- 84
- 85 /* si on est dans le père */
- 86 if(id_fils){
- 87
- 88 pause();
- 95
- 98 }else{
- 108 if(gestion_redirection(num_cmd,-1,desc_pipe_lecture)){
- 109 execvp((cmd->seq[num_cmd])[0],cmd->seq[num_cmd]);
- 110 perror("Erreur lors du lancement du programme" );
- 111 }
- 123 }
|
|