#include #include // Per exit(), abort() #include // Per fork(), getpid() #include // Per pid_t #include // Per waitpid() e le macro int main() { pid_t pid1, pid2; int wstatus; pid_t pid_terminato; // --- Primo figlio (che terminerà correttamente) --- pid1 = fork(); if(pid1 < 0) { perror("fork"); exit(EXIT_FAILURE); } if (pid1 == 0) { sleep(1); // Diamo tempo al padre di mettersi in attesa printf("[FIGLIO %d] termino con stato 42.\n", getpid()); exit(42); // Uscita normale con valore 42 } // --- Secondo figlio (che terminerà con un segnale) --- pid2 = fork(); if(pid2 < 0) { perror("fork"); exit(EXIT_FAILURE); } if (pid2 == 0) { sleep(1); // Diamo tempo al padre di mettersi in attesa printf("[FIGLIO %d] genero un errore (abort).\n", getpid()); abort(); // Termina con un segnale (SIGABRT) } // --- Codice del Padre --- printf("[PADRE] Ho creato i figli %d e %d. Ora attendo...\n", pid1, pid2); // Usiamo un loop per attendere TUTTI i figli int figli_raccolti = 0; while (figli_raccolti < 2) { pid_terminato = wait(&wstatus); // Attende un figlio qualsiasi figli_raccolti++; printf("[PADRE] Raccolto il figlio %d.\n", pid_terminato); // Analisi 'wstatus' if (WIFEXITED(wstatus)) { // Caso 1: Uscita normale (exit()) // Recuperiamo il valore passato a exit() int exit_status_figlio = WEXITSTATUS(wstatus); printf("[PADRE]\t\t Il figlio %d è terminato NORMALMENTE ed ha restituito %d.\n", pid_terminato, exit_status_figlio); } else if (WIFSIGNALED(wstatus)) { // Caso 2: Uscita anormale (segnale) // Recuperiamo il numero del segnale int segnale_ricevuto = WTERMSIG(wstatus); printf("[PADRE]\t\t Il figlio %d è terminato da un SEGNALE: %d.\n", pid_terminato, segnale_ricevuto); } else { printf("[PADRE]\t\t Il figlio %d è terminato in un altro modo.\n", pid_terminato); } } printf("[PADRE] Tutti i figli sono stati raccolti. Termino.\n"); return 0; }