System signal processing in Go

Source: Internet
Author: User
This is a creation in Article, where the information may have evolved or changed.

The system we operate in production requires an elegant exit, that is, after the program receives the exit notification, there is a chance to execute a cleanup code before the finishing touches are finished and then really quits. We use System signal to notify the system to exit, that is, kill Pragram-pid. We set up a processing function for some system signals in the program, and when the signal is received, it executes the relevant cleanup program or notifies each child process to do self-cleanup. Kill-9 Mandatory kill program is unacceptable, which will cause some processing process is forced to break, leaving the unrecoverable scene, causing the message to be destroyed, affecting the next system startup run.

An agent that was recently implemented with Golang also needs an elegant exit, so I try to understand how the system signal is handled in Golang, and share it with you. Golang system signal processing mainly involves the OS package, the Os.signal package, and the Syscall package. The most important of these functions is the Notify function in the signal package:

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

The function forwards the system signal received by the process to channel C. Which signals are forwarded is determined by the variable parameters of the function, and if you do not pass in the sig parameter, then notify forwards all signals received by the system to C. If you call notify like this:

Signal. Notify (c, Syscall. SIGINT, Syscall. SIGUSR1, Syscall. SIGUSR2)

Then go will only focus on the type of signal you passed in, and the other signal will be handled by default, mostly process exits. So you need to pass in notify the types of signal you want to focus on and deal with, which is to intercept them and provide custom handlers to change their behavior.

The following is a more complete example:

Signal.go

Package Main

Import "FMT"
Import "Time"
Import "OS"
Import "Os/signal"
Import "Syscall"

Type Signalhandler func (S OS. Signal, Arg interface{})

Type Signalset struct {
M Map[os. Signal]signalhandler
}

Func signalsetnew () (*signalset) {
SS: = new (Signalset)
SS.M = Make (Map[os. Signal]signalhandler)
return SS
}

Func (set *signalset) register (s OS. Signal, Handler Signalhandler) {
If _, Found: = Set.m[s];!found {
Set.m[s] = Handler
}
}

Func (set *signalset) handle (SIG OS. Signal, Arg interface{}) (err error) {
If _, Found: = Set.m[sig]; Found {
Set.m[sig] (SIG, Arg)
return Nil
} else {
Return to FMT. Errorf ("No handler available for signal%v", SIG)
}

Panic ("won ' t reach here")
}

Func Main () {
Go Syssignalhandledemo ()
Time. Sleep (time. Hour)//Make the main goroutine wait!
}

Func Syssignalhandledemo () {
SS: = Signalsetnew ()
Handler: = func (S OS). Signal, Arg interface{}) {
Fmt. PRINTF ("Handle signal:%v\n", s)
}

Ss.register (Syscall. SIGINT, Handler)
Ss.register (Syscall. SIGUSR1, Handler)
Ss.register (Syscall. SIGUSR2, Handler)

for {
c: = Make (chan os. Signal)
var sigs []os. Signal
For sig: = Range SS.M {
SIGs = Append (SIGs, SIG)
}
Signal. Notify (c)
SIG: = <-c

ERR: = Ss.handle (sig, Nil)
if (err! = nil) {
Fmt. PRINTF ("Unknown signal received:%v\n", SIG)
Os. Exit (1)
}
}
}

In the example above, the Notify function has only one parameter and does not pass in the sig to be followed, so the program forwards all the type signal received to channel C. Build the source file and execute the program:

$> Go Build signal.go
$> Signal

Under another window, execute the following command:
$> Ps-ef|grep Signal
Tonybai 25271 1087 0 16:27 pts/1 00:00:00 signal
$> Kill-n 2 25271
$> kill-n 12 25271
$> Kill 25271

We will see the following output in the first window:
$> Signal
Handle Signal:interrupt
Handle Signal:user defined Signal 2
Unknown signal received:terminated

In Syssignalhandledemo we can also pass in a collection of signal that we care about for notify:

Signal. Notify (c, sigs ...)

This way only the signals in the set can be captured, and the program exits more directly when it receives a signal that is not in the collection. Above is just a demo, just shows that we can capture our attention to the signal, does not reflect the program how to gracefully exit, different procedures to exit the different ways, there is no common method, do not elaborate, your program needs your special design.

In addition, the process of our production environment is mostly in the form of Daemon daemon. The programs we implemented with C refer to the methods in "Advanced UNIX Programming" to convert the program to daemon process, but there are some implementations on the go, but it is said to be unsatisfactory. More go developers recommend not implementing daemon transformations in your code, and recommend using third-party tools directly. For example, under Ubuntu we can easily convert your program to daemon using the Start-stop-daemon applet:

$> Start-stop-daemon–start–pidfile./signal.pid–startas/home/tonybai/test/go/signal–background-m
$> Start-stop-daemon–stop–pidfile./signal.pid–startas/home/tonybai/test/go/signal

Note: Pidfile can only be created successfully with the-M option.

Start-stop-daemon is the default version of the Debian Linux distribution. However, there is no such tool in the Redhat Linux distribution, and we can install it ourselves:

Wget-c http://developer.axis.com/download/distribution/apps-sys-utils-start-stop-daemon-IR1_9_18-2.tar.gz
Tar-xzf apps-sys-utils-start-stop-daemon-ir1_9_18-2.tar.gz
CD Apps/sys-utils/start-stop-daemon-ir1_9_18-2
GCC Start-stop-daemon.c-o Start-stop-daemon

Switch to Root
CP start-stop-daemon/sbin/
chmod +x/sbin/start-stop-daemon

In addition the binary installation package provided by Go 1.0.2 directly in Redhat 5.6 (Linux tonybai 2.6.18-238.el5 #1 SMP Sun Dec 14:22:44 EST. x86_64 x86_64 x86_64 GNU /linux) error running below, prompted to find the GLIBC 2.7 version. The current approach to solving this problem seems to be only compiled from the source code installation. Go to $goroot/src, execute./all.bash. The go executable after you reproduce the link is working.

, Bigwhite. All rights reserved.

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.