Newsgroup: it.comp.os.linux.development
Titolo: SIGPROF e SIGUSR1

Salve! Vi spiego il mio problema. Nel mio programma ho bisogno di fare una
data operazione ogni 5 secondi, e quando si verifica una certa condizione
continuare normalmente e avviare un timer che dopo 2 secondi mi stampa, ad
esempio, "pippo". Quindi, ogni 5 secondi stampare "paperina", e quando
succede qualcosa continuare con la stampa di paperina ogni 5 secondi, però
stampando "pippo" 2 secondi dopo questo evento.
Primo ho messo un timer ITIMER_REAL che ogni 5 secondi mi richiama la
funzione static void gestoreTimer(int). Poi si verifica il dato evento,
richiamato dal segnale SIGUSR1, e imposto all'interno del gestore del
SIGUSR1 un altro timer, ITIMER_PROF, che dopo 2 secondi dovrà generare il
segnale SIGPROF. Il gestore di SIGPROF poi mi stampa "pippo".
Il problema è che il primo timer funziona correttamente. Poi quando ricevo
SIGUSR1 il codice che setta il timer ITIMER_PROF viene effettivamente
eseguito, quindi il timer ITIMER_PROF viene settato. Invece il timer non
scade mai e il segnare SIGPROF non viene mai generato. Come mai? Forse non
è possibile usare i timer ITIMER_PROF e ITIMER_REAL contemporaneamente? Non
ho letto niente di simile nella man pages. Grazie mille.
Segue un po' di codice:
main{
  timer.it_interval.tv_sec  = timer.it_value.tv_sec  = 5;
  timer.it_interval.tv_usec = timer.it_value.tv_usec = 0;
  if (setitimer (ITIMER_REAL, &timer, NULL) < 0) {
    perror ("setitimer ");
    exit (1);
  }
  signal (SIGALRM, gestoreTimer);
  signal (SIGUSR1, gestoreSigusr1);
  signal (SIGPROF, gestoreTimerIncendio);
  [...] // un po' di codice vario che gira all'infinito.
}
static void gestoreSigusr1 (int segnale) {
    timer.it_interval.tv_sec  = 1;
    timer.it_interval.tv_usec = 0;
    timer.it_value.tv_sec  = 1;
    timer.it_value.tv_usec = 0;
    if (setitimer (ITIMER_PROF, &timer, NULL) < 0) {
      perror ("setitimer ");
      exit (1);
    }
 
    return;
}
static void gestoreTimerIncendio (int segnale) {
   pippo = 1 - pippo;
}
-- 
Lo guardo' in viso, e riconobbe tutti gli uomini che aveva incontrato
durante la sua vita.

 scade mai e il segnare SIGPROF non viene mai generato. Come mai? Forse non
non ho seguito bene tutto il discorso, ma guardando di
sfuggita il codice vedo che non ripristini i signal
handlers.
In parole povere alla fine delle funzioni che vengono
chiamate a seguito della ricezione del segnale(sighandlers), 
devi riusare la chiamata signal per far riassociare le
funzioni in questione nuovamente ai relativi signum.
Se cosi' non fai vengono i signum vengono riassociati
al valore di default SIG_DFL (azione di default prevista 
per quel segnale).
Saluti,
-- 
MoonChild
Togliere nospam per l' esatta e-mail 
UIN-ICQ: 3634753 

 
Non è necessario, la semantica di signal prevede di usare l'handler 
definito finchè non ne specifichi un altro.
Comunque concordo sul fatto che il suo discorso fosse di difficile 
comprensione :-)
Bye, AM

 Saluti,
-- 


 comprensione :-)
Beh... sì. Anche io c'ho capito poco :) In poche parole devo avere due timer
separati. Uno che scatta ogni cinque secondi, per sempre. L'altro che
scatta dopo 2 secondi e poi mai più. Niente pippo che insegue paperina e
cose simili ;)


 definito finchè non ne specifichi un altro.
Credo che dipenda dalle implementazioni, forse viene resettato
solo negli UNIX System V (a lavoro sviluppo su Solaris, e li'
sono sicuro lo resetti a SIG_DFL).
Leggendo l' altra risposta di Danilo (data l' ora non fatto
una prova :)) sembra che su Linux sia come dici tu, cioe' che 
rimanga attiva l' assegnazione. 
Il fatto che venga normalmente sempre reimpostato e' allora 
per un discorso di portabilita'.
Ciao,


   if (setitimer (ITIMER_REAL, &timer, NULL) < 0) {
Scopro solo ora l' esistenza di questa syscall e dalla lettura della
manpage
direi che posso continuare senza.
quello che preoccupa, oltre la sua progettazione, e' la sezione BUGS:
"
BUGS
    Under Linux, the generation and delivery of a signal are distinct, and
    there each signal is permitted only one outstanding event.  It's
there-    fore conceivable that under pathologically heavy  loading, 
ITIMER_REAL
    will  expire  before  the  signal  from  a previous expiration has been
    delivered.  The second signal in such an event will be lost.
"
Comunque io ho sempre seguito altri approcci, sia con SIGALRM per eventi
asincroni (precisione del secondo)  sia nei cicli di select().
Al problema informatico mi e' venuta in aiuto una struttura dati
come Priority-queue (libro consigliato R. Sedgewich) e un uso un po'
complesso. Il tempo e' un' ascissa, quindi basta ordinare PER TEMPO
ASSOLUTO
tutti gli eventi che devono succedersi (se un evento deve succedere tra 
10 sec. e uno tra 20 le chiavi di accodamento saranno 10 + time() e
20 + time() ). Dalla coda con priorita' si estrae sempre l' elemento con
priorita' piu' alta, quindi basta settare un timeout mappato con il suo
handler al valore estratto - time(). All' esecuzione di ogni handler,
in uscita si deve chiamare una apposita funzione per settare il prossimo
timeout mappato con il suo relativo handler. Se un timeout va riarmato,
si fa push nella priortyqueue del timeout + time() con associato un field
con reference all' handler di gestione.
Non so consigliarti altro che cambiare approccio e non usare quella
syscall,
ma magari qualcuno puo' suggerirti un modo per non snaturare troppo il
tuo codice.
ciao
Roberto.
-- 
questo articolo e` stato inviato via web dal servizio gratuito 
http://www.newsland.it/news
 segnala gli abusi ad 
ab...@newsland.it

 handler al valore estratto - time(). 
[...] 
Come detto sopra, quest'idea mi sembra adatta al mio scopo... però è un po'
troppo complessa da implementare e visto il tempo ristretto a disposizione
preferisco piuttosto togliere di mezzo l'idea dei due timer e rinunciare a
qualcosa. Poi vedrò. 
La cosa che mi sembra strana è che, sia da utente normale che da root, i
timer ITIMER_PROF e ITIMER_VIRTUAL sembrano non scadere mai. Perchè? 
Il bello è che nella documentazione viene suggerito di usare entrambi questi
timer per calcolare il tempo trascorso da un'applicazione in kernel space e
nello user space. Il bello è che nemmeno uno di questi scade mai :( Misteri
del kernel. 
Mi sorge un'altra domanda sui timer, ma mi sembra il caso di metterla in
post separato. 
Ciao Ciao. DaN
