Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Golang catch signals

I want to implement a "process wrapper" in Go. Basically what it will do, is launch a process (lets say a node server) and monitor it (catch signals like SIGKILL, SIGTERM ...)

I think the way to do is to launch the node server in a go routine using syscall.Exec:

func launchCmd(path string, args []string) {   err := syscall.Exec(path, args, os.Environ())   if err != nil {     panic(err)   } } 

Then I'd like to catch every possible signals generated by the command executed by syscall. I'm pretty new to Go, any help would be appreciated.

like image 219
rmonjo Avatar asked Aug 07 '13 14:08

rmonjo


People also ask

How do you catch signals in Golang?

Unix signal can be easily handled in Golang by using the os/signal package. We need to use a channel of type os. Signal to read signals. You can implement code to handle every type of Unix signal received by the program.

What is a signal channel Golang?

As per the golang documentation, “Channels are a typed conduit through which you can send and receive values with the channel operator, <- .” A channel allows one goroutine to signal another goroutine about a particular event.

What is the difference between SIGTERM and Sigkill?

The SIGTERM signal is a generic signal used to cause program termination. Unlike SIGKILL , this signal can be blocked, handled, and ignored. It is the normal way to politely ask a program to terminate. The shell command kill generates SIGTERM by default.

What is os signal?

Signals are standardized messages sent to a running program to trigger specific behavior, such as quitting or error handling. They are a limited form of inter-process communication (IPC), typically used in Unix, Unix-like, and other POSIX-compliant operating systems.


1 Answers

There are three ways of executing a program in Go:

  1. syscall package with syscall.Exec, syscall.ForkExec, syscall.StartProcess
  2. os package with os.StartProcess
  3. os/exec package with exec.Command

syscall.StartProcess is low level. It returns a uintptr as a handle.

os.StartProcess gives you a nice os.Process struct that you can call Signal on. os/exec gives you io.ReaderWriter to use on a pipe. Both use syscall internally.

Reading signals sent from a process other than your own seems a bit tricky. If it was possible, syscall would be able to do it. I don't see anything obvious in the higher level packages.

To receive a signal you can use signal.Notify like this:

sigc := make(chan os.Signal, 1) signal.Notify(sigc,     syscall.SIGHUP,     syscall.SIGINT,     syscall.SIGTERM,     syscall.SIGQUIT) go func() {     s := <-sigc     // ... do something ... }() 

You just need to change the signals you're interested in listening to. If you don't specify a signal, it'll catch all the signals that can be captured.

You would use syscall.Kill or Process.Signal to map the signal. You can get the pid from Process.Pid or as a result from syscall.StartProcess.

like image 171
Luke Avatar answered Sep 28 '22 05:09

Luke