PDA

Visualizza la versione completa : [c]Interrompere esecuzione funzione alla ricezione di un segnale


njno
03-03-2009, 13:24
Ciao a tutti, vi spiego qual'è il mio problema.
Ho una funzione che deve processare dei dati rispettando dei vincoli di tempo. Supponiamo che il tempo a sua disposizione sia di 10 msec. Entro tale tempo la funzione deve ritornare il risultato prodotto (anche se incompleto, la cosa fondamentale è il rispetto del vincolo temporale).
L' idea è quella di settare un timer a 10 msec, attraverso la funzione ualarm, prima di invocare la mia funzione. Allo scadere del timer il processo riceverà il segnale SIGALRM che indicherà la fine del tempo a disposizione per l'esecuzione della funzione.
Il problema è che dopo aver gestito il segnale, attraverso la funzione signal o sigaction, il programma ritorna ad eseguire dal punto in cui era stato interrotto, cioè la funzione ritornerà ad essere eseguita fino alla sua conclusione ignorando il vincolo temporale.
Per farvi capire meglio, quello che voglio ottenere è un comportamento simile a quello che ha la funzione select alla ricezione di un segnale, essa ritorna -1 e setta la variabile globale errno a EINTR indicante che la funzione è stata interrota da un segnale.
Conoscete un modo per rendere la funzione interrompibile dall'esterno al verificarsi di un evento?(nel mio caso la ricezione del segnale SIGALRM).
Qualsiasi idea, suggerimento o spunto di discussione è ben accetto.
Ringrazio tutti in anticipo.

njno

P.S. Sistema operativo Debian.

MItaly
03-03-2009, 15:58
Nel gestore del segnale imposta un flag globale che indica alla funzione di terminare il calcolo. Imposta la funzione in modo che ad ogni step del calcolo verifichi questo flag e se è impostato termini il calcolo; ovviamente il flag va resettato al termine della funzione.

njno
05-03-2009, 15:25
Per prima cosa mi scuso per il fatto di non aver risposto subito.

Avevo pensato anche io a questa soluzione, però non mi piace l'idea di aggiungere un controllo prima di ogni istruzione della funzione.

Originariamente inviato da MItaly
Nel gestore del segnale imposta un flag globale che indica alla funzione di terminare il calcolo. Imposta la funzione in modo che ad ogni step del calcolo verifichi questo flag e se è impostato termini il calcolo; ovviamente il flag va resettato al termine della funzione.

Posto come ho risolto il problema in caso possa tornare utile a qualsiasi altro utente del forum.
Navigando fra le man pages di linux ho trovato le funzioni setjmp e longjmp. Ecco cosa dice il manuale:

setjmp: save stack context for non-local goto
longjmp: non-local jump to a saved stack context

Entrambe le funzione vogliono come parametro una variabile di tipo jmp_buf, la prima per memorizzare il punto da cui riprendere l'esecuzione, la seconda per riprendere l'esecuzione dal punto indicato nel parametro che gli passiamo.
Detto ciò, ecco cosa ho fatto

ho creato una variabile globale di tipo jmp_buf chiamandola return_point
ho creato una variabile globale di tipo int chiamandola timer_elapsed. (se è 1 tempo scaduto)
prima di invocare la funzione tempo critica, imposto il timer, setto timer_elapsed a 0 e invoco
setjmp passandogli come parametro return_point
dopo ciò ho inserito un controllo per vedere se siamo arrivati in questo punto dell'esecuzione a casua dello scadere del timer o per il normale flusso di esecuzione del programma. Sè scaduto il timer vado avanti, altrimenti invoco la funzione tempo critica.
Nel gestore del segnale, invece, setto la variabile timer_elapsed=1 e invoco longjmp passandogli come parametro return_point. Questo fa si che l'esecuzione riprende dal punto in cui è stata invoca la setjmp e non si invochi la funzione tempo critica perchè la variabile timer_elapsed indica che siamo in quel punto a causa dello scadere del timer.


Spero di essere stato chiaro durante l'esposizione della soluzione.

Ovviamente ringrazio MItaly per il tempo dedicatomi.

Saluti

njno

Loading