This is a creation in Article, where the information may have evolved or changed.
Signal processing in the Golang
个平台的信号定义或许有些不同。下面列出了POSIX中定义的信号。Linux 使用34-64信号用作实时系统中。命令 man signal 提供了官方的信号介绍。在POSIX.1-1990标准中定义的信号列表
Signal |
value |
Action |
Description |
SIGHUP |
1 |
Term |
Terminal Control process End (terminal connection disconnected) |
SIGINT |
2 |
Term |
User sends Intr character (CTRL + C) trigger |
Sigquit |
3 |
Core |
User sends the Quit character (ctrl+/) trigger |
Sigill |
4 |
Core |
Illegal instruction (program error, attempt to execute data segment, stack overflow, etc.) |
Sigabrt |
6 |
Core |
Call the Abort function to trigger |
SIGFPE |
8 |
Core |
Arithmetic run error (floating-point arithmetic error, divisor is zero, etc.) |
SIGKILL |
9 |
Term |
Unconditional End Program (cannot be captured, blocked, or ignored) |
SIGSEGV |
11 |
Core |
Invalid memory reference (attempting to access memory space that does not belong to itself, write to read-only memory space) |
Sigpipe |
13 |
Term |
Message pipeline Corruption (Fifo/socket communication, the pipeline is not open and writes) |
Sigalrm |
14 |
Term |
Clock timing Signal |
SIGTERM |
15 |
Term |
End program (can be captured, blocked, or ignored) |
SIGUSR1 |
30,10,16 |
Term |
User Retention |
SIGUSR2 |
31,12,17 |
Term |
User Retention |
SIGCHLD |
20,17,18 |
Ign |
Child process End (received by parent process) |
Sigcont |
19,18,25 |
Cont |
Continue execution of stopped processes (cannot be blocked) |
SIGSTOP |
17,19,23 |
Stop |
Stop a process (cannot be caught, blocked, or ignored) |
Sigtstp |
18,20,24 |
Stop |
Stop a process (can be caught, blocked, or ignored) |
Sigttin |
21,21,26 |
Stop |
Triggers when the daemon reads data from the terminal |
Sigttou |
22,22,27 |
Stop |
Triggers when a background program writes data to the terminal |
- List of signals in the SUSV2 and posix.1-2001 standards:
Signal |
value |
Action |
Description |
SIGTRAP |
5 |
Core |
TRAP instruction triggers (such as breakpoints, used in the debugger) |
Sigbus |
0,7,10 |
Core |
Illegal address (memory address alignment error) |
Sigpoll |
|
Term |
Pollable event (Sys V). Synonym for SIGIO |
Sigprof |
27,27,29 |
Term |
Performance clock signal (includes system call time and process consuming CPU time) |
Sigsys |
12,31,12 |
Core |
Invalid system call (SVR4) |
Sigurg |
16,23,21 |
Ign |
Emergency data arrives at socket (4.2BSD) |
Sigvtalrm |
26,26,28 |
Term |
Virtual clock signal (process consumes CPU time) (4.2BSD) |
Sigxcpu |
24,24,30 |
Core |
CPU time resource limit exceeded (4.2BSD) |
Sigxfsz |
25,25,31 |
Core |
File size resource limit exceeded (4.2BSD) |
第1列为信号名;第2列为对应的信号值,需要注意的是,有些信号名对应着3个信号值,这是因为这些信号值与平台相关,将man手册中对3个信号值的说明摘出如下,the first one is usually valid for alpha and sparc, the middle one for i386, ppc and sh, and the last one for mips.第3列为操作系统收到信号后的动作,Term表明默认动作为终止进程,Ign表明默认动作为忽略该信号,Core表明默认动作为终止进程同时输出core dump,Stop表明默认动作为停止进程。第4列为对信号作用的注释性说明,浅显易懂,这里不再赘述。需要特别说明的是,SIGKILL和SIGSTOP这两个信号既不能被应用程序捕获,也不能被操作系统阻塞或忽略。
- The difference between kill PID and Kill-9 PID
kill pid的作用是向进程号为pid的进程发送SIGTERM(这是kill默认发送的信号),该信号是一个结束进程的信号且可以被应用程序捕获。若应用程序没有捕获并响应该信号的逻辑代码,则该信号的默认动作是kill掉进程。这是终止指定进程的推荐做法。
kill -9 pid则是向进程号为pid的进程发送SIGKILL(该信号的编号为9),从本文上面的说明可知,SIGKILL既不能被应用程序捕获,也不能被阻塞或忽略,其动作是立即结束指定进程。通俗地说,应用程序根本无法“感知”SIGKILL信号,它在完全无准备的情况下,就被收到SIGKILL信号的操作系统给干掉了,显然,在这种“暴力”情况下,应用程序完全没有释放当前占用资源的机会。事实上,SIGKILL信号是直接发给init进程的,它收到该信号后,负责终止pid指定的进程。在某些情况下(如进程已经hang死,无法响应正常信号),就可以使用kill -9来结束进程。
若通过kill结束的进程是一个创建过子进程的父进程,则其子进程就会成为孤儿进程(Orphan Process),这种情况下,子进程的退出状态就不能再被应用进程捕获(因为作为父进程的应用程序已经不存在了),不过应该不会对整个linux系统产生什么不利影响。
- How the app gracefully exits
Linux Server端的应用程序经常会长时间运行,在运行过程中,可能申请了很多系统资源,也可能保存了很多状态,在这些场景下,我们希望进程在退出前,可以释放资源或将当前状态dump到磁盘上或打印一些重要的日志,也就是希望进程优雅退出(exit gracefully)。
从上面的介绍不难看出,优雅退出可以通过捕获SIGTERM来实现。具体来讲,通常只需要两步动作:1)注册SIGTERM信号的处理函数并在处理函数中做一些进程退出的准备。信号处理函数的注册可以通过signal()或sigaction()来实现,其中,推荐使用后者来实现信号响应函数的设置。信号处理函数的逻辑越简单越好,通常的做法是在该函数中设置一个bool型的flag变量以表明进程收到了SIGTERM信号,准备退出。2)在主进程的main()中,通过类似于while(!bQuit)的逻辑来检测那个flag变量,一旦bQuit在signal handler function中被置为true,则主进程退出while()循环,接下来就是一些释放资源或dump进程当前状态或记录日志的动作,完成这些后,主进程退出。
signal send and process in go
- The processing of signals in Golang mainly uses the two methods in the Os/signal package:
- The Notify method is used to listen for incoming signals.
- The Stop method is used to cancel the listener
1. Monitor all Signals
package mainimport ( "fmt" "os" "os/signal")// 监听全部信号func main() { //合建chan c := make(chan os.Signal) //监听所有信号 signal.Notify(c) //阻塞直到有信号传入 fmt.Println("启动") s := <-c fmt.Println("退出信号", s)}
启动go run example-1.go启动ctrl+c退出,输出退出信号 interruptkill pid 输出退出信号 terminated
2. Monitor the specified signal
package mainimport ( "fmt" "os" "os/signal" "syscall")// 监听指定信号func main() { //合建chan c := make(chan os.Signal) //监听指定信号 ctrl+c kill signal.Notify(c, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2) //阻塞直到有信号传入 fmt.Println("启动") //阻塞直至有信号传入 s := <-c fmt.Println("退出信号", s)}
启动go run example-2.go启动ctrl+c退出,输出退出信号 interruptkill pid 输出退出信号 terminatedkill -USR1 pid 输出退出信号 user defined signal 1kill -USR2 pid 输出退出信号 user defined signal 2
3. Gracefully exit the Go daemon
Package Mainimport ("FMT" "OS" "Os/signal" "Syscall" "Time")//Graceful exit Go daemon func main () {//Create Listen quit Chan c: = Make (chan os. Signal)//monitor the specified signal CTRL + C kill Signal. Notify (c, Syscall. SIGHUP, Syscall. SIGINT, Syscall. SIGTERM, Syscall. Sigquit, Syscall. SIGUSR1, Syscall. SIGUSR2) go func () {for s: = range C {Switch s {case Syscall. SIGHUP, Syscall. SIGINT, Syscall. SIGTERM, Syscall. Sigquit:fmt. Println ("Exit", s) exitfunc () Case Syscall. Sigusr1:fmt. Println ("USR1", s) case Syscall. Sigusr2:fmt. Println ("USR2", s) default:fmt. Println ("Other", s)}}} () Fmt. PRINTLN ("Process start ...") Sum: = 0 for {sum++ fmt. Println ("sum:", sum) time. Sleep (time. Second)}}func Exitfunc () {fmt. Println ("Start exiting ...") fmt. Println ("Perform cleanup ...") fmt. Println ("End exit ...") OS. Exit (0)}
kill -USR1 pid 输出usr1 user defined signal 1kill -USR2 pid usr2 user defined signal 2kill pid 退出 terminated开始退出...执行清理...结束退出...
执行输出go run example-3.go进程启动...sum: 1sum: 2sum: 3sum: 4sum: 5sum: 6sum: 7sum: 8sum: 9usr1 user defined signal 1sum: 10sum: 11sum: 12sum: 13sum: 14usr2 user defined signal 2sum: 15sum: 16sum: 17退出 terminated开始退出...执行清理...结束退出...
Reference
http://www.cnblogs.com/jkkkk/p/6180016.htmlhttp://blog.csdn.net/zzhongcy/article/details/50601079https://www.douban.com/note/484935836/https://gist.github.com/reiki4040/be3705f307d3cd136e85#file-signal-go-L1