Newsgroup: it.comp.os.linux.development
Titolo: Tenere traccia del numero di figli

Salve a tutti,
ho un processo A che genera un tot di figli, dopodiche' si mette a
fare altro. I figli fanno quello che devono, e infine escono.
Vorrei che il processo A terminasse quando tutti i figli hanno
terminato. Ma non posso fare semplicemente un loop di wait(), il
processo A ha altro da fare, non si deve mettere in attesa dopo i
fork.
Come potrei fare? Pensavo di intercettare SIGCHLD e scalare un
contatore, quando arrivo a 0 tutti i figli sono terminati, ma ci sono
un po' di race condition che non so come evitare. Inoltre, e'
affidabile contare i SIGCHLD?
Qualche schema di massima? Qualche suggerimento?
Thx,
Pleg

Ciao,
usa un main loop dentro ad A, chiamando waitpid () con l'opzione
WNOHANG.
Controllane il valore di ritorno, la macro WIFEXITED dovrebbe fare al
caso tuo.
Matteo


 caso tuo.
E anche stavolta mi salvi, grazie mille :))
Pleg

Pero'...
Ora devo aggiungere un pezzo: il parent (A) genera tutti i children, e
per ognuno apre uno pseudo-terminale diverso, dandogli il descrittore
slave.
L'idea e': i child sono in realta' programmi indipendenti (il parent
fa fork + execl) che _pensano_ di star comunicando tra loro tramite
porta seriale (ognuno dovrebbe essere su un pc diverso), invece il
parent raccoglie i dati e li ridirige al destinatario (simulando la
rete di telecomunicazione fisica).
Quindi: il mio parent, dopo aver generato i child, si mette in un loop
infinito con una bella select all'inizio. Appena un child spedisce dei
dati sul suo lato dello pseudo-terminale, la select scatta, il parent
legge il bytestream e simula la rete, manipolando e ridirigendo il
bytestream verso il destinatario.
Cioe', al momento il mio main loop e' totalmente asincrono, fatto
scattare dalla select.
Quale potrebbe essere il modo piu' semplice e pulito di aggiungere
waitpid() con WNOHANG? Dici che basta dare un timeout alla select,
cosi' ogni tanto esce, controllo il waitpid, e ritorno alla select? O
puo' bascondere insidie?
Thx,
Pleg

 puo' bascondere insidie?
Sì, a livello logico va bene, basta un ciclo while su un intero (il
numero di fd aperti, o di processi in esecuzione) che sia > 0.
select () ritorna 0 se viene raggiunto il timeout senza che alcun
descrittore sia cambiato, ma devi controllare sempre con waitpid. Puoi
farlo ad es. ogni secondo.
L'unico dubbio che ho di questo approccio è: se un figlio termina
l'esecuzione, chiude anche gli fd a lui associati. Cosa succede a
select? Ritorna normalmente, o ritorna EBADF? Questo non me lo
ricordo.
Ciao,
matteo


[...]
In realtà ho appena letto "man select_tut".
Dicono di evitare i timeout se possibile, e di usare al loro posto un
gestore di eventi (SIGCHLD ad esempio).
Quando arriva il segnale SIGCHLD, il gestore imposta una variabile
condivisa "got_SIGCHLD" ad 1. La select in seguito ritorna con EINTR,
e si può gestire correttamente il caso di un figlio terminato.
Ti consiglio di fare così anche tu. Lascia perdere il mio ultimo
messaggio. Questo metodo è molto migliore.
Ciao,
Matteo

Gia', mi ero scordati dei descrittori.
Ok, studiero' questo metodo col gestore di eventi.
Grazie ancora!
Pleg

Pleg ha scritto:

Per mescolare segnali e select, un metodo alternativo, se ti interessa, 
ï¿œ la selfpipe; ne trovi una descrizione (+motivazione +api) su 
www.skarnet.org/software/skalibs/selfpipe.html
 (e da altre parti, ma 
penso che questa sia la spiegazione piï¿œ comprensibile, per giunta 
corredata da un'implementazione molto banale da leggere).
In pratica, in corrispondenza a un segnale (qui SGCHLD) genera un evento 
su un descrittore; tu inserisci questo descrittore fra quelli che stai 
monitorando, e la select ti avvisa anche quando ricevi i segnali.
<caveat>
A suo tempo sono rimasto folgorato dall'idea della selfpipe, per cui 
sono tutto tranne che imparziale ;D
</caveat>

 </caveat>
Si vede che non hai mai visto kqueue di FreeBSD ;-)
Ciao  Manlio Perillo

 è la selfpipe;
A quanto pare, la pselect() e' stata introdotta proprio per sopperire
a quella mancanza di select() e rimpiazzare la selfpipe :)
Pleg

 Ciao  Manlio Perillo
ciao

 Pleg
Eretico! Infedele! convertiti alla selfpipe! Al rogo! Al rogo! ;) ;) ;)