Signal ()

Da Gambas-it.org - Wikipedia.

La funzione

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(): [Nota 1]

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


In quest'altro esempio, nel quale verrà utilizzata la Classe "Timer" anziché un ciclo, si provocherà la chiusura del programma, quando si premeranno i tasti Ctrl+\ :

Private tm As Timer


Library "libc:6"

Private Const SIGQUIT As Integer = 3

' __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(SIGQUIT, sighandler)
 
 With tm = New Timer As "Tempus"
   .Delay = 1000
   .Start
 End With
    
End


Private Procedure sighandler(signum As Integer)
 
 Print "Raccolto il segnale: "; signum; " - Termine del programma."
 tm.Stop
 Quit
 
End

Public Sub Tempus_Timer()
 
 Print "Ciclo con attesa di 1 secondo..."
 
End


Note

[1] Vedi anche la pagina relativa alla funzione alarm()