Using Go os.Signal, os.Interrupt, and os.Kill Signals

2022年11月20日 5042点热度 1人点赞 0条评论
内容目录
package main

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

func main() {
	// Set up channel on which to send signal notifications.
	// We must use a buffered channel or risk missing the signal
	// if we're not ready to receive when the signal is sent.
	c := make(chan os.Signal, 1)
	signal.Notify(c, os.Interrupt)

	// Block until a signal is received.
	s := <-c
	fmt.Println("Got signal:", s)
}

The definition of the Notify function is as follows:

func Notify(c chan<- os.Signal, sig ...os.Signal) 

os.Signal represents signals, and there are various kinds of signals, such as Interrupt and Kill, so it needs to be received via a channel to avoid losing signals.

	c := make(chan os.Signal, 1)

Then listen for types of signals:

	signal.Notify(c, os.Interrupt, os.Kill)

os.Interrupt denotes an interrupt;
os.Kill denotes a kill;

Under normal circumstances, the process is terminated when Ctrl+C is pressed. However, if it subscribes to signals, it can continue running without stopping.

The following example can receive two signals and perform some operations before exiting the process:

package main

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

func main() {
	ci := make(chan os.Signal, 1)
	ck := make(chan os.Signal, 1)
	sleep := make(chan bool, 1)

	signal.Notify(ci, os.Interrupt)
	signal.Notify(ck, os.Kill)
	go interrupt(ci, sleep)
	go kill(ck, sleep)

	<-sleep
}
func interrupt(ci chan os.Signal, sleep chan bool) {
	s := <-ci
	fmt.Println("Process interrupted:", s)
	sleep <- true
}

func kill(ck chan os.Signal, sleep chan bool) {
	s := <-ck
	fmt.Println("Process killed", s)
	sleep <- true
}

Pressing Ctrl+C:

file

Of course, if it's a Kill signal, the process might be killed directly without any prompt.

Killing the process from the task manager:

file
file

If it’s in Linux, there may still be some effect.

file

To stop listening for signals:

signal.Stop(ci)

Supported signals in Go:

| Signal Value | Value | Action | Description |
| :----------- | :------- | :----- | :----------------------------------------------------------- |
| SIGHUP | 1 | Term | Terminal control process ends (terminal connection disconnect)|
| SIGINT | 2 | Term | User sends INTR character (Ctrl+C) trigger |
| SIGQUIT | 3 | Core | User sends QUIT character (Ctrl+/) trigger |
| SIGILL | 4 | Core | Illegal instruction (program error, attempting to execute data segment, stack overflow, etc.) |
| SIGABRT | 6 | Core | Triggered by calling abort function |
| SIGFPE | 8 | Core | Arithmetic error (floating point error, division by zero, etc.) |
| SIGKILL | 9 | Term | Unconditionally terminate the program (cannot be caught, blocked, or ignored) |
| SIGSEGV | 11 | Core | Invalid memory access (attempting to access unowned memory, writing to read-only memory) |
| SIGPIPE | 13 | Term | Message pipe broken (FIFO/Socket communication when writing to a closed pipe) |
| SIGALRM | 14 | Term | Clock timer signal |
| SIGTERM | 15 | Term | End the program (can be caught, blocked, or ignored) |
| SIGUSR1 | 30,10,16 | Term | User defined |
| SIGUSR2 | 31,12,17 | Term | User defined |
| SIGCHLD | 20,17,18 | Ign | Child process ends (received by the parent process) |
| SIGCONT | 19,18,25 | Cont | Continue execution of a stopped process (cannot be blocked)|
| SIGSTOP | 17,19,23 | Stop | Stop the process (cannot be caught, blocked, or ignored) |
| SIGTSTP | 18,20,24 | Stop | Stop the process (can be caught, blocked, or ignored) |
| SIGTTIN | 21,21,26 | Stop | Triggered when a background program reads from the terminal |
| SIGTTOU | 22,22,27 | Stop | Triggered when a background program writes to the terminal |

Additional example:

package main

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

func main() {
	SigChan := make(chan os.Signal, 1)

	signal.Notify(SigChan, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)

	sig := <-SigChan

	switch sig {
	case syscall.SIGHUP:
		fmt.Println("\nSIGHUP signal generated")

	case syscall.SIGINT:
		fmt.Println("\nSIGINT signal generated")

	case syscall.SIGTERM:
		fmt.Println("\nSIGTERM signal generated")

	case syscall.SIGQUIT:
		fmt.Println("\nSIGQUIT signal generated")

	default:
		fmt.Println("\nUNKNOWN signal generated")
	}
}

痴者工良

高级程序员劝退师

文章评论