Golang signal processing and how to implement a process exit gracefully detail
- 2020-06-12 09:30:08
- OfStack
Signal types in THE Linux system
Signal definitions may vary from operating system to operating system. The signals defined in POSIX are listed below.
In linux, 34-64 signals are used for real-time systems.
Command man 7 signal provides the official signal presentation. You can also use ES15en-ES16en for quick viewing
In the list, signals numbered 1 to 31 are supported by traditional UNIX and are unreliable (non-real-time), while signals numbered 32 to 63 are later expanded and called reliable (real-time). The difference between an unreliable signal and a reliable signal is that the former does not support queuing and may cause signal loss, while the latter does not.
For example, x86, ia64,ppc and s390 have three values. The first value is slpha and sparc. The middle value is ix86,ia64, ppc, s390, arm and sh. Hyphen - indicates that the architecture is not supported by this signal,
The first column is the signal name;
The second column is the corresponding signal value. It should be noted that some signal names correspond to 3 signal values, because these signal values are related to the platform. The description of 3 signal values in man manual is as follows. the first usually valid sparc, the middle for i386, ppc and sh, one one for mips.
The third list is the actions of the operating system after receiving the signal, Term indicates the default action is to terminate the process, Ign indicates the default action is to ignore the signal, Core indicates the default action is to terminate the process and output core dump, Stop indicates the default action is to stop the process.
The fourth column is an explanatory note on the role of signals.
Standard signals - ES83en.1-1990 definitions
Signal Value Action Comment
----------------------------------------------------------------------
SIGHUP 1 Term Hangup detected on controlling terminal
or death of controlling process
SIGINT 2 Term Interrupt from keyboard
SIGQUIT 3 Core Quit from keyboard
SIGILL 4 Core Illegal Instruction
SIGABRT 6 Core Abort signal from abort(3)
SIGFPE 8 Core Floating point exception
SIGKILL 9 Term Kill signal
SIGSEGV 11 Core Invalid memory reference
SIGPIPE 13 Term Broken pipe: write to pipe with no
readers
SIGALRM 14 Term Timer signal from alarm(2)
SIGTERM 15 Term Termination signal
SIGUSR1 30,10,16 Term User-defined signal 1
SIGUSR2 31,12,17 Term User-defined signal 2
SIGCHLD 20,17,18 Ign Child stopped or terminated
SIGCONT 19,18,25 Cont Continue if stopped
SIGSTOP 17,19,23 Stop Stop process
SIGTSTP 18,20,24 Stop Stop typed at tty
SIGTTIN 21,21,26 Stop tty input for background process
SIGTTOU 22,22,27 Stop tty output for background process
SIGKILL and SIGSTOP signals cannot be captured, blocked, or ignored.
Standard Signals - DEFINITION of SUSv2 and POSIX, 1-2001
Signal Value Action Comment
--------------------------------------------------------------------
SIGBUS 10,7,10 Core Bus error (bad memory access)
SIGPOLL Term Pollable event (Sys V).
Synonym for SIGIO
SIGPROF 27,27,29 Term Profiling timer expired
SIGSYS 12,-,12 Core Bad argument to routine (SVr4)
SIGTRAP 5 Core Trace/breakpoint trap
SIGURG 16,23,21 Ign Urgent condition on socket (4.2BSD)
SIGVTALRM 26,26,28 Term Virtual alarm clock (4.2BSD)
SIGXCPU 24,24,30 Core CPU time limit exceeded (4.2BSD)
SIGXFSZ 25,25,31 Core File size limit exceeded (4.2BSD)
As early as Linux 2.2SIGSYS, SIGXCPU, SIGXFSZ and SIGBUS (non-sparc and mips architectures) the default operation was to terminate the process (but not to produce coredump)
In some unix systems, THE SIGXCPU and SIGXFSZ signals are used to terminate the process and do not generate coredunp. Since Linux 2.4 these signals have generated coredump.
Standard signal - other signals
Signal Value Action Comment
--------------------------------------------------------------------
SIGIOT 6 Core IOT trap. A synonym for SIGABRT
SIGEMT 7,-,7 Term
SIGSTKFLT -,16,- Term Stack fault on coprocessor (unused)
SIGIO 23,29,22 Term I/O now possible (4.2BSD)
SIGCLD -,-,18 Ign A synonym for SIGCHLD
SIGPWR 29,30,19 Term Power failure (System V)
SIGINFO 29,-,- A synonym for SIGPWR
SIGLOST -,-,- Term File lock lost
SIGWINCH 28,28,20 Ign Window resize signal (4.3BSD, Sun)
SIGUNUSED -,31,- Term Unused signal (will be SIGSYS)
Signal 29 is SIGINFO or SIGPWR in alpha, but SIGLOST in sparc.
SIGEMT is not defined in ES128en.1-2001, but it is not in most Unix plays. The default is coredump and terminates the process.
SIGPWR (not defined in ES133en.1-2001) is ignored by default.
SIGIO (not defined in ES138en.1-2001) is also ignored in some Unix systems.
kill pid is used to send SIGTERM (the default signal sent by kill) to a process with process number pid, which is a signal to terminate the process and can be captured by the application. If the application does not capture and respond to the logical code for the signal, the default action for the signal is kill to drop the process. This is the recommended practice for terminating a specified process.
kill-9 pid sends SIGKILL (the signal number is 9) to a process with process number pid. As explained above, SIGKILL cannot be captured, blocked or ignored by the application, and its action is to terminate the specified process immediately. In layman's terms, the application can't "sense" the SIGKILL signal at all, and it is completely unprepared and killed by the operating system receiving the SIGKILL signal. Obviously, in this "violent" situation, the application has no opportunity to free up the resources it is currently occupying. In fact, the SIGKILL signal is sent directly to the init process, which, upon receiving the signal, is responsible for terminating the process specified by pid. In some cases (such as when the process is dead with hang and cannot respond to a normal signal), es161EN-9 can be used to terminate the process.
1 if kill through the end of the process is to create a child of the parent process, will become an orphan, his son process (Orphan Process), in this case, the child process exit status can't be applied process to capture (because as a parent application no longer exists), but should not be any adverse impact on the entire linux system.
Signal transmission and processing in Go
Sometimes we want to process the Signal signal in an Go program, such as gracefully closing the program after receiving the SIGTERM signal (see the application in the next section). The Go signal notification mechanism can be sent to 1 channel
os.Signal
The implementation. So let's first create 1
os.Signal channel
, and then use
signal.Notify
Register the signal to be received.
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
)
func main() {
sigs := make(chan os.Signal, 1)
done := make(chan bool, 1)
// signal.Notify(c)
signal.Notify(sigs, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGINT, syscall.SIGTERM)
go func() {
sig := <-sigs
fmt.Println(sig)
done <- true
}()
fmt.Println("wait for signal")
<- done
fmt.Println("got signal and exit")
fmt.Println("run done")
}
How do I implement a graceful exit of a process
What is a graceful exit in the first place? The so-called elegant exit is actually to avoid killing the process by violence. After receiving the signal, the process will automatically do some post-treatment and then exit voluntarily.
Linux Server server-side applications often run long time, in the process of running, may apply for a lot of system resources, can also save a lot of state, in these scenarios, we hope to process before exiting, can release the resources or the current state of dump to disk or print some important log, is hope process graceful exit (exit gracefully).
As you can see from the above introduction, graceful exits can be achieved by capturing SIGTERM. To be specific, it usually takes only two steps:
1) Register the handler function of SIGTERM signal and do some preparation for process exit in the handler function. Signal-processing function registration is available
signal()
or
sigaction()
The latter is recommended for setting up the signal response function. The simpler the logic of the signal processing function, the better. The common practice is to set an flag variable of type bool in this function to indicate that the process has received an SIGTERM signal and is ready to exit.
2) in the main process
main()
In, by something like
while(!bQuit)
1 once bQuit is set as true in signal handler function, the main process exits the while() loop, followed by 1 action to release the resource or the current status or logging of the dump process, after which the main process exits.
This in front of me 1 article also introduced [= [golang httpserver graceful restart] [1]] https: / / www ofstack. com article / 137069. htm, it introduces the 1, how do we use httpserver graceful restart, it also introduced some signals using 1, grace and restart the train of thought. Today we are going to show you how to exit gracefully, which is a simplified version of how to restart gracefully.
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
)
func main() {
sigs := make(chan os.Signal, 1)
// done := make(chan bool, 1)
// signal.Notify(sigs)
// signal.Notify(sigs, os.Interrupt, os.Kill, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGINT, syscall.SIGTERM)
signal.Notify(sigs, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
// go func() {
// sig := <-sigs
// fmt.Println(sig)
// done <- true
// }()
go func() {
for s := range sigs {
switch s {
case syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT:
fmt.Println("got signal and try to exit: ", s)
do_exit()
case syscall.SIGUSR1:
fmt.Println("usr1: ", s)
case syscall.SIGUSR2:
fmt.Println("usr2: ", s)
default:
fmt.Println("other: ", s)
}
}
}()
fmt.Println("wait for signal")
i := 0
for {
i++
fmt.Println("times: ", i)
time.Sleep(1 * time.Second)
}
// <- done
fmt.Println("got signal and exit")
fmt.Println("run done")
}
func do_exit() {
fmt.Println("try do some clear jobs")
fmt.Println("run done")
os.Exit(0)
}
kill -USR1 pid
usr1 user defined signal 1
kill -USR2 pid
usr2 user defined signal 2
kill -QUIT pid
got signal and try to exit: quit
try do some clear jobs
run done
conclusion