Signal ()
La funzione della libreria di C
void (*signal(int signum, void (*sighandler)(int)))(int);
gestisce i segnali che riguardano il programma, chiamando una funzione particolare in presenza di un determinato segnale. Signal(), dunque, associa un determinato segnale, indicato dal parametro signum, alla chiamata della funzione sighandler. Questo secondo parametro è più specificatamente un Puntatore a funzione (se ne dovrà tenere conto poi usando tale funzione nel codice Gambas), e può essere impostato in uno dei tre seguenti modi:
- SIG_DFL : viene eseguita dal processo l'azione prevista dal segnale indicato nel primo parametro;
- SIG_IGN : il segnale (fatta eccezione per SIGKILL e SIGSTOP), indicato nel primo parametro, è ignorato;
- una Funzione, stabilita dall'utente ed avente un parametro di tipo Intero, che sarà attivata dal segnale indicato nel primo parametro. Il valore di questo parametro sarà anche passato al parametro di tipo Intero della Funzione chiamata.
Volendola utilizzare in Gambas, bisognerà dichiararla con Extern, nonché dichiarare la libreria di C: libc.so.6, nella quale la funzione è contenuta:
Private Extern signal(signum As Integer, sighandler As Pointer) As Integer In "libc:6"
Semplice esempio di uso in Gambas congiuntamente con la funzione alarm():
Library "libc:6" Private Const SIGALRM As Integer = 14 ' void (*signal(int signum, void (*sighandler)(int)))(int) ' Sets a function to handle signal i.e. a signal handler with signal number sig. Private Extern signal(signum As Integer, sighandler As Pointer) As Integer ' unsigned int alarm(unsigned int seconds) ' Schedule an alarm. Private Extern alarm(seconds As Integer) As Integer ' void exit (int __status) ' Terminate program execution with STATUS. Private Extern exit_C(status As Integer) Exec "exit" Public Sub Form_Open() ' Gestione del segnale SIGALRM: signal(SIGALRM, post_alarm) ' Attivazione del segnale di allarme dopo 3 secondi: alarm(3) End Private Function post_alarm(segno As Integer) ' "segno" passa il valore del 1° parametro di "signal()" Print "\nRicevuto il segnale "; segno; " - Termine del programma" exit_C(0) End
Esempio con applicazione a riga di comando
Lo stesso esempio può essere fatto con un'applicazione a riga di comando. In questo caso, però, deve essere utilizzato un ciclo nella procedura principale, dal quale si uscirà solo quando si attiverà la funione alarm():
Private bo As Boolean = True Library "libc:6" Private Const SIGALRM As Integer = 14 ' void (*signal(int signum, void (*sighandler)(int)))(int) ' Set the handler for the signal SIG to HANDLER. Private Extern signal(signum As Integer, wait_alarm As Pointer) ' unsigned int alarm(unsigned int seconds) ' Schedule an alarm. Private Extern alarm(seconds As Integer) As Integer Public Sub Main() signal(SIGALRM, wait_alarm) ' gestione del segnale SIGALRM ' Il segnale di allarme scatterà dopo 4 secondi: alarm(4) ' Attiviamo il ciclo per impedire che il processo giunga subito al termine: While bo Sleep 0.01 Wend End Private Procedure wait_alarm(isignal As Integer) Print "\nRicevuto il segnale "; isignal; " - Termine programma" ' Per terminare il programma, assegnamo il valore "False" alla variabile booleana "bo": bo = False End
oppure usando la funzione pause() della libreria unistd.h:
Library "libc:6" Private Const SIGALRM As Integer = 14 ' void (*signal(int signum, void (*sighandler)(int)))(int) ' Set the handler for the signal SIG to HANDLER. Private Extern signal(signum As Integer, wait_alarm As Pointer) ' unsigned int alarm(unsigned int seconds) ' Schedule an alarm. Private Extern alarm(seconds As Integer) As Integer ' int pause (void) ' Suspend the process until a signal arrives. Private Extern pause() As Integer Public Sub Main() signal(SIGALRM, wait_alarm) ' gestione del segnale SIGALRM ' Il segnale di allarme scatterà dopo 4 secondi: alarm(4) ' Invochiamo la funzione esterna "pause()" che sospenderà il processo ' sino a quando non giungerà il segnale: pause() End Private Procedure wait_alarm(isignal As Integer) Print "\nRicevuto il segnale "; isignal; " - Termine programma" End
Si può scrivere un codice per creare un ciclo temporizzato, come se si usasse la Classe Timer di Gambas:
Private v As Boolean Private i As Integer Library "libc:6" Private Const SIGALRM As Integer = 14 ' void (*signal(int signum, void (*sighandler)(int)))(int) ' Set the handler for the signal SIG to HANDLER. Private Extern signal(signum As Integer, wait_alarm As Pointer) ' unsigned int alarm(unsigned int seconds) ' Schedule an alarm. Private Extern alarm(seconds As Integer) As Integer Public Sub Main() signal(SIGALRM, wait_alarm) alarm(1) v = True ' Attiviamo il ciclo per impedire che il processo giunga subito al termine: While v Wend Main() End Private Procedure wait_alarm(isignal As Integer) Inc i Print "Secondi trascorsi: "; i v = False End
In quest'altro esempio si provocherà la chiusura del programma, quando si premeranno i tasti Ctrl+C:
Library "libc:6" Private Const SIGINT As Integer = 2 ' __sighandler_t signal (int __sig, __sighandler_t __handler) ' Set the handler for the signal SIG to HANDLER. Private Extern signal(__sig As Integer, __handler As Pointer) As Integer Public Sub Main() signal(SIGINT, sighandler) While True Print "Ciclo con attesa di 1 secondo..." Sleep 1 Wend End Private Procedure sighandler(signum As Integer) Print "Raccolto il segnale: "; signum; " - Termine del programma." Quit End
Vedi anche la pagina relativa alla funzione alarm()