Newsgroup: it.comp.os.linux.development
Titolo: Simulazione Ctrl-C

In un PC con Linux 7.1 di Suse, ho realizzato un programma
in C che crea alcuni processi figli, e dovrebbe ucciderli tutti
automaticamente quando termina.
Quando il programma viene terminato con Ctrl-C va tutto
bene, ma in tutti gli altri casi (return, exit, abort, raise(SIGINT),
ecc.) i processi figli vengono inesorabilmente agganciati al
processo con pid 1, e continuano tranquillamente a girare.
Qualcuno sa darmi una mano a risolvere questo problema?
Grazie grazie grazie... Ciao!
Null

 Qualcuno sa darmi una mano a risolvere questo problema?
man waitpid
Ciao,
 Emmanuele.

Null wrote:

Ciao,
Contrariamente a quanto asserisci il processo padre (parent), al termine
della sua esecuzione, non uccide automaticamente i figli (children). Invece
è importante che il padre attenda il completamento di ciascuno dei processi
figli, altrimenti ogni child che finisce rimane nel sistema nello stato di
"zombie" fino a che il parent termina e a quel punto il processo child
"orfano" è ereditato dal processo PID 1 (Init). Quest'ultimo prima o poi
eseguirà una funzione per la cancellazione di questi children che saranno
quindi eliminati dal sistema.
Poiché il processo parent può essere un qualche daemon che rimane in
esecuzione fino allo spegnimento della macchina può accadere che il sistema
si intasi nel gestire centinaia di processi "zombie".
In sintesi è buona regola usare le API wait(), waitpid() e waitid() per
intercettare i children terminati e controllarne lo stato con la macro
WIFEXITED(status) in combinazione con WEXITSTATUS(status). In questo modo
ci si assicura che i children non diventino zombies e/o che non siano
trasferiti al controllo di PID 1 (Init). Per ragioni che non sto ad
approfondire è preferibile usare solo waitid(), presente anche in Linux
dalla release 2.6.9.
Nel caso in cui uno o più processi figli non terminino in tempi accettabili,
se un'ulteriore attesa non è praticabile li si deve uccidere spedendogli
qualche segnale. Dopo di che sarà sempre possibile controllarne il buon
esito della suddetta operazione attraverso l'uso della macro
WIFSIGNALED(status) in combinazione con WTERMSIG(status).
Buon lavoro.
fabio de francesco

 "orfano" è ereditato dal processo PID 1 (Init).
Nel mio caso il padre attende con una waitpid.
I figli sono processi che non dovrebbero terminare mai,
tranne in caso di problemi alle system call.
Non devo inviare esplicitamente segnali dal padre ai figli.
Nel caso in cui un processo figlio termini (ad esempio per
un errore ad una system call), il padre se ne accorge tramite
una waitpid, e a questo punto vorrei avere un comportamento
simile a quello che si ha qudno si da` Ctrl-C, ossia la
terminazione del processo padre e dei processi figli, ma
senza inviare esplicitamente segnali ai figli (sempre che
sia possibile), appunto mi piacerebbe sapere come
viene interpretato il Ctrl-C.
Ciao e Grazie.
Null

 Null
Ciao
Roberto.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 i daemon.
Rileggendo il post iniziale mi sono reso conto che ho capito il problema
al contrario. Tu non vuoi daemonizzare niente, anzi, vuoi che con il
padre vengano eliminati tutti i figli.
Comunque sia il Control-C funziona cosi' per i motivi che ti ho detto,
perche' ogni figlio eredita il tty (terminale di gestione) del padre
e perche' non solo leaders di gruppo di processi.
Quindi se vuoi sterminare tutti con un SIGINT mandato al padre, o questi
ha un signal handler che manda un kill a tutti i figli prima di chiamare
exit() o si deve far in modo che un segnal mandato al padre come leader
di gruppo di processi, sia distribuito a tutto il gruppo.
Il contrario di quanto suggerito prima.
man 2 setpgid
e
man 2 setpgrp
Non l' ho mai fatto, pero' so che la soluzion e' li'.
scusa l' equivoco.


 Null
Tutti i processi iniziati tramite la Shell sono children di quest'ultima. La
Shell li mette in esecuzione con fork() ed exec() e poi rimane in waitpid()
oppure waitid() per ciascuno dei children. Quando una waitX() ritorna viene
interrogato lo status per scoprire la causa della terminazione del child.
Come già scritto più sopra, nel caso di terminazione di un qualsiasi child
per il segnale SIGINT (Ctrl-C), anche tutti gli altri processi dello stesso
process group che è attualmente in foreground sono terminati tramite
l'invio dello stesso segnale.
In sintesi lo "raise" di un segnale, qualsiasi sia la sua provenienza, è
equiparato alla generazione di un interrupt che blocca immediatamente il
processo e trasferisce il controllo al kernel esattamente dove si trova la
Interrupt Service Routine predisposta alla gestione del segnale
(interrupt). La ISR relativa al segnale SIGINT attua di default la
terminazione del processo oppure trasferisce il controllo di nuovo in user
space nel caso sia stata registrata, con sigaction(), una funzione
alternativa da eseguirsi al ricevimento del segnale.
Per avere, come tu chiedi, un comportamento simile a quello che si ha nel
caso di un Ctrl-C cioè la terminazione di tutti i processi dello stesso
process group nel caso in cui un qualunque child si interrompa per un
qualsiasi errore ti conviene:
1) Lasciare il parent in attesa con waitid() o waitpid().
2) Se la waitX ritorna verificare lo status per conoscerne il motivo.
3) Se è il caso inviare a tutti i processi children, oppure a tutti i
processi dello stesso process group uno specifico segnale che sarà
intercettato e gestito. E' preferibile che si invii un segnale definito
dall'utente e che possa essere intercettato (SIGUSR1/SIGUSR2) piuttosto che
un generico SIGKILL (non gestibile) perché probabilmente è meglio avere la
possibilità di terminare ogni singolo processo in modo "ordinato e pulito".
Se ritieni che anche un brutale SIGKILL possa andare ti si eviterà il
lavoro di scrivere una routine di chiusura.
4) (Eventualmente) terminare il processo corrente (parent).
Nel tuo specifico caso, per essere sicuro di segnalare e quindi terminare
tutti i processi dello stesso gruppo, userei le API killpg(<pgid>,SIGUSR1)
oppure kill(-<pgid>,SIGUSR1) (attenzione al segno '-' nel secondo caso; le
parentesi angolari delimitano il testo da sostituire con il process
identification group del processo corrente che è ottenibile con
getpgid(0)). 
Saluti.
fabio de francesco
PS.: Spero di non avere scritto qualche c****ta nella fretta. Nel caso
fatemi sapere, please.

<cut>
Grazie mille!
Ciao.
Null

 ha scritto nel messaggio 
news:4416f13b$0$29720$4faf...@reader2.news.tin.it...
<cut>
Grazie per la risposta esauriente.
Ciao.
Null