Segnali

Un segnale è una notifica semantica dal sistema operativo, o generata dal sistema
stesso o generata da un altro processo Linux, oppure anche inviata dall'utente tramite il terminale di controllo.
Per esempio Ctrl-C invia il segnale SIGINT (interruzione) al processo in foreground.

Vi sono approssimativamente 35 segnali diversi in Linux.

I segnali si possono gestire col package os/signal.

(640signals.go):

package main

import ("fmt"; "os"; "os/signal"; "syscall")

func main() {
	// Channel che riceve le notifiche di segnali
	sigs := make(chan os.Signal, 1)
	// Channel che riceve notifica di uscita
	done := make(chan bool, 1)
	// Registrazione dei segnal accettati sul channel
	signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)

	// Goroutine che si blocca in attesa di un segnale.
	go func() {
		sig := <-sigs
		fmt.Println()
		fmt.Println(sig)
		// Indica al main che può uscire
		done <- true
	}()

	// Main: attesa di segnale ed uscita
	fmt.Println("awaiting signal")
	<-done
	fmt.Println("exiting")
}

I segnali vengono ricevuti su un channel apposito.

Tranne il segnale SIGKILL, tutti gli altri segnali si possono ignorare o gestire. Un segnale non esplicitamente ignorato o gestito ha un comportamento di default, che di solito è la terminazione del processo.

La funzione Notify indica quali segnali sono accettati e gestiti. La funzione Ignore indicherebbe quali segnali sono ignorati.

La ricezione di un segnale non ignorato e non gestito, causa in Go una terminazione immediata con stack trace e dump dello stato dei registri di CPU.

E' buona norma gestire sempre il segnale SIGTERM, che è una richiesta educata di terminazione e da l'opportunità al programma di chiudere ogni risorsa e salvare il suo stato se lo desidera.