2011-12-06 13 views
13

In un sistema che esegue Linux 2.6.35+ il mio programma crea molti processi figli e li monitora. Se un processo figlio muore, eseguo un po 'di pulizia e di nuovo il processo. Io uso signalfd() per ottenere il segnale SIGCHLD nel mio processo. signalfd viene utilizzato in modo asincrono utilizzando libevent.Gestione di più SIGCHLD

Quando si utilizzano gestori di segnale per segnali non in tempo reale, mentre il gestore di segnali è in esecuzione per un particolare segnale, è necessario bloccare l'occorrenza dello stesso segnale per evitare di entrare in ricorsivi gestori. Se più segnali arrivano in quel momento, il kernel invoca il gestore una sola volta (quando il segnale è sbloccato).

È lo stesso comportamento quando si utilizza signalfd()? Dal momento che la gestione basata su signalfd non presenta i problemi tipici associati all'esecuzione asincrona dei normali gestori di segnale, stavo pensando che il kernel possa code tutte le altre occorrenze di SIGCHLD?

Qualcuno può chiarire il comportamento di Linux in questo caso ...

risposta

17

Su Linux, più i bambini che terminano prima di leggere un SIGCHLD con signalfd() saranno compressi in un unico SIGCHLD. Questo significa che quando si legge il segnale SIGCHLD, si deve pulire dopo tutti i bambini che sono terminati:

// Do this after you've read() a SIGCHLD from the signalfd file descriptor: 
while (1) { 
    int status; 
    pid_t pid = waitpid(-1, &status, WNOHANG); 
    if (pid <= 0) { 
     break; 
    } 
    // something happened with child 'pid', do something about it... 
    // Details are in 'status', see waitpid() manpage 
} 

Vorrei sottolineare che ho in effetti visto questa compressione del segnale quando due bambini procedato terminato al contemporaneamente. Se facevo solo un singolo waitpid(), uno dei bambini che terminava non veniva gestito; e il ciclo precedente lo ha risolto.

corrispondente documentazione:

+0

Grazie .. un paio di domande ..
Diciamo che ci sono molti eventi nella coda di epoll che non sono ancora stati svuotati dal mio processo. In questo caso stai dicendo che il kernel accoderà solo un evento di lettura per SIGCHLD sul signalfd anche se n processi muoiono? Informazioni sull'utilizzo di waitpid() in un ciclo, il problema che ho con questo approccio è che si ottiene solo lo stato di uscita del processo figlio, ma si perdono altre informazioni che si otterrebbero dalla strucf signalfd_siginfo quando si legge da signalfd (o siginfo_t quando si usa sigaction). Immagino che non ci sia modo di ottenerlo? – Manohar

+0

@Santhosh nota che epoll non mette in coda gli eventi del descrittore di file nel senso letterale di esso; piuttosto, riporta solo lo stato dei descrittori di file (leggibilità, scrittura). Quindi quando gli eventi si verificano su un descrittore di file che lo rende leggibile, non importa quanti ce ne siano - epoll segnalerà solo la leggibilità.E la prossima volta che esegui un epoll_wait(), farà esattamente la stessa cosa (eccetto se usi epoll con trigger edge), ma ancora non riporterà il numero di eventi). Riguardo la struttura signalfd_siginfo, credo che tu abbia ragione. Ma di cosa avresti bisogno da lì in caso di SIGCHLD comunque? –

+2

@Santhosh: notare anche che signalfd() stesso comprime i segnali SIGCHLD, non epoll. Questo significa che non solo non otterrai più eventi da epoll, ma riceverai solo un segnale SIGCHLD dal read(); la struct signalfd_siginfo degli altri sarà persa per sempre. –

0

in realtà il modo senza problemi sarebbe la waitfd funzionale che permetterà di aggiungere un pid specifica per eseguire il polling()/epoll(). Sfortunatamente, non è stato accettato da Linux anni fa quando è stato proposto.

+2

Ho davvero intenzione di aggiungilo come commento, non una risposta, mi dispiace. –

Problemi correlati