/** * * @File : exo_04.cxx * * @Authors : A. B. Dragut * * @Date : 2011 * * @Synopsis : Un pere cree CstNbreFils fils. Le ieme fils dort i secondes. * le pere attend la mort de chaque fils avec waitpid() et l'analyse * avec WIFEXITED et WEXITSTATUS(status) * ATTENTE PASSIVE CORRECTE! * **/ #include #include #include #include // atoi() #include // SIGCHLD #include // pause(), sleep() #include "CExc.h" #include "nsSysteme.h" // Fork(), Signal() using namespace std; using namespace nsSysteme; // Fork(), Signal() #define GETSTATUS(status) (((status) >> 8) & 0xff) namespace { volatile sig_atomic_t qIlYADesFilsTermines; void TraitantPourLesFils(int sigNum) { qIlYADesFilsTermines = 1; } void TraitantQuelconque(int sigNum) { cout << "Bonjour, un signal " << sigNum << " est arrive.\n"; } } // namespace anonyme int main(int argc, char * argv []) { try { if (3 > argc) throw CExc("main()",string ("Usage : ") + argv [0] + " ..."); qIlYADesFilsTermines = 0; struct sigaction Action; Action.sa_handler = TraitantPourLesFils; Action.sa_flags = 0; sigemptyset (& Action.sa_mask); Sigaction (SIGCHLD, & Action, 0); Action.sa_handler = TraitantQuelconque; Action.sa_flags = 0; sigemptyset (& Action.sa_mask); Sigaction (SIGINT, & Action, 0); const int CstNbrFils = atoi (argv [1]); if (CstNbrFils < 1 || CstNbrFils > 20) throw CExc("main()","Nombre de fils non compris entre 1 et 20"); ::pid_t TabPid [CstNbrFils]; ::pid_t TabEtat [CstNbrFils]; if(argc != CstNbrFils + 2) { throw CExc("main()",string ("Usage : ") + argv [0] + " ..."); } sigset_t MasqueBlock,MasqueUnBlock; sigemptyset (&MasqueBlock); sigaddset (&MasqueBlock, SIGCHLD); sigaddset (&MasqueBlock, SIGINT); sigemptyset (&MasqueUnBlock); Sigprocmask (SIG_BLOCK, & MasqueBlock, 0); for (int i (0); i < CstNbrFils ; i++ ) { if (! (TabPid [i] = Fork ())) { return ::sleep (atoi(argv[i+2])); } else { cout << "Fils de pid " << TabPid [i] << " lance pour " << (atoi(argv[i+2])) << " secondes.\n"; TabEtat[i] = 1; // vivant } } for(int ilYAEncoreAutantDeFils (CstNbrFils); ilYAEncoreAutantDeFils;) { cout << "En attente, car il me reste " << ilYAEncoreAutantDeFils << " fils...\n"; ::sigsuspend(&MasqueUnBlock); if(!qIlYADesFilsTermines) { continue; } qIlYADesFilsTermines = 0; for(int kFils(0); kFils < CstNbrFils; kFils++) { int status; if(0 == TabEtat[kFils]) { continue; } cout << "Recuperation du status fils " << TabPid[kFils] << " ... "; ::pid_t leFils (Waitpid(TabPid[kFils],&status,WNOHANG)); if(!leFils) { cout << "encore en vie.\n"; continue; } cout << " ok.\n"; TabEtat[kFils] = 0; ilYAEncoreAutantDeFils --; cout << "Le fils de pid " << leFils << " est termine "; if (WIFEXITED(status)) { cout << "par un exit ou return de " << WEXITSTATUS (status); } if (WIFSIGNALED(status)) { cout << "par reception du signal " << WTERMSIG(status); if(status & 0x80) { cout << " et a egalement cree un fichier core."; } } cout << "\n"; } // fin de la boucle de recuperation des status pour // le signal courant } cout << "Tout va bien, le pere a egalement fini son travail.\n"; return 0; } catch (const CExc & Exc) { cerr <