2016-05-23 17 views
5

Ho processo genitore, che deve creare alcuni processi figli. Il modo migliore che ho trovato è l'utilizzo di fork + execl. Ma poi il processo genitore deve sapere se execl figlio fallisce o meno, e non so come implementarlo.Il modo migliore per creare processi figlio in linux e gestire possibili errori

 int pid = fork(); 
     if (pid < 0) { 
      std::cout << "ERROR on fork." << std::endl; 
     } if (pid == 0) { 
      execl("/my/program/full/path", (char *)NULL); 
      exit(1); 
     } 
     else { 
      if (/*child's process execl fails*/) { 
       std::cout << "it failed" << std::endl 
      } else { 
       std::cout << "child born" << std::endl 
      } 
     } 

penso che questa idea non è buono:

int status(0); 
sleep(100); 
int res = waitpid(pid, &status, WNOHANG); 
if (res < 0 && errno == 10) { 
    std::cout << "it failed" << std::endl 
} else { 
    std::cout << "child born" << std::endl 
} 

perché non è bene sperare che il processo figlio morirà dopo 100 millisecondi, voglio sapere per certo come solo quella volontà accade.

Penso anche che la creazione di shared_memory o di una speciale connessione di pipe per tale controllo sia un Cannon against Bees.

Ci deve essere una soluzione semplice, che non ho ancora trovato.

Qual è il modo migliore per farlo?

+0

Basta usare 'popen' e controllare il valore restituito. – Andrew

+0

Diciamo che è ancora vivo, come posso essere sicuro che execl non ha fallito? Forse è fallito, e process è vivo solo perché non ha ancora completato l'istruzione 'exit (1)'. – Arkady

+0

Vuoi controllare che il tuo processo sia stato eseguito correttamente * lanciato *, o che * completato * e * abbia restituito uno stato di zero *? I due sono piuttosto diversi. – Andrew

risposta

1

Come soluzione generale è possibile registrare il gestore di segnali (SIGUSR1) nel genitore utilizzando sigaction().

In un bambino: annullare la registrazione del gestore di segnale, se la chiamata execl() non è riuscita, è necessario inviare SIGUSR1 al genitore.

Nel genitore: ogni pid figlio memorizzeremo in std :: set. Quando vengono creati tutti i child, devi solo creare un thread separato per tenere traccia dei childs. Nella funzione thread chiama semplicemente wait() e rimuove pid dal set. Un altro modo per ascoltare il segnale SIGCHLD (ma porterà a una soluzione più complessa, quindi se si genera un altro thread è un'opzione che utilizzerei thread).

Quando il set è vuoto abbiamo fatto.

+0

Sembra una buona soluzione generica. Ci ho pensato senza un segnale speciale, ma con il segnale sembra addirittura logicamente completato. Grazie. – Arkady