Introduction
The gproc
component provides a unified signal listening and callback processing feature, aimed at resolving the pain points of redundant signal processing logic among multiple different components in a program and the inability to destruct smoothly after receiving exit signals. Without a component for unified exit signal listening, when multiple components use goroutine
for asynchronous signal listening, the main goroutine
often exits directly upon receiving an exit signal or waits for an unpredictable amount of time to exit, which prevents the program from exiting smoothly and may trigger some unexpected issues. gproc
enables each component to receive exit signals effectively and perform corresponding deconstruction processing through unified signal registration and callback processing, ensuring that the program's signal processing logic is more rigorous.
Relevant methods:
// AddSigHandler adds custom signal handler for custom one or more signals.
func AddSigHandler(handler SigHandler, signals ...os.Signal)
// AddSigHandlerShutdown adds custom signal handler for shutdown signals:
// syscall.SIGINT,
// syscall.SIGQUIT,
// syscall.SIGKILL,
// syscall.SIGTERM,
// syscall.SIGABRT.
func AddSigHandlerShutdown(handler ...SigHandler)
// Listen blocks and does signal listening and handling.
func Listen()
Brief Introduction:
- The
AddSigHandler
method is used for adding listeners and corresponding callback function registrations for specified signals. - The
AddSigHandlerShutdown
method is used for adding listeners and corresponding callback function registrations for common process exit signals, allowing registration of multipleSigHandler
. - The
Listen
method is for blocking signal listening and automatically executing callback function calls.
Let's look at two examples.
Example 1, Using Standard Library Signal Listening
The common code logic for using the standard library signal listening mechanism is as follows:
package main
import (
"fmt"
"os"
"os/signal"
"syscall"
"time"
)
func signalHandlerForMQ() {
var (
sig os.Signal
receivedChan = make(chan os.Signal)
)
signal.Notify(
receivedChan,
syscall.SIGINT,
syscall.SIGQUIT,
syscall.SIGKILL,
syscall.SIGTERM,
syscall.SIGABRT,
)
for {
sig = <-receivedChan
fmt.Println("MQ is shutting down due to signal:", sig.String())
time.Sleep(time.Second)
fmt.Println("MQ is shut down smoothly")
return
}
}
func main() {
fmt.Println("Process start, pid:", os.Getpid())
go signalHandlerForMQ()
var (
sig os.Signal
receivedChan = make(chan os.Signal)
)
signal.Notify(
receivedChan,
syscall.SIGINT,
syscall.SIGQUIT,
syscall.SIGKILL,
syscall.SIGTERM,
syscall.SIGABRT,
)
for {
sig = <-receivedChan
fmt.Println("MainProcess is shutting down due to signal:", sig.String())
return
}
}
We execute it via the go run
command, then exit using the Ctrl+C
shortcut (Command+C
for Mac users).
$ go run signal_handler.go
Process start, pid: 21928
^CMainProcess is shutting down due to signal: interrupt
MQ is shutting down due to signal: interrupt
As you can see, unfortunately, the MQ
goroutine
is forcibly closed before it is fully exited.
Example 2, Using gproc
Signal Listening
The improved signal listening mechanism using the gproc
component is as follows:
package main
import (
"fmt"
"github.com/gogf/gf/v2/os/gproc"
"os"
"time"
)
func signalHandlerForMQ(sig os.Signal) {
fmt.Println("MQ is shutting down due to signal:", sig.String())
time.Sleep(time.Second)
fmt.Println("MQ is shut down smoothly")
}
func signalHandlerForMain(sig os.Signal) {
fmt.Println("MainProcess is shutting down due to signal:", sig.String())
}
func main() {
fmt.Println("Process start, pid:", os.Getpid())
gproc.AddSigHandlerShutdown(
signalHandlerForMQ,
signalHandlerForMain,
)
gproc.Listen()
}
We execute it via the go run
command, then exit using the Ctrl+C
shortcut (Command+C
for Mac users).
$ go run signal_handler_gproc.go
Process start, pid: 22876
^CMQ is shutting down due to signal: interrupt
MainProcess is shutting down due to signal: interrupt
MQ is shut down smoothly
See the difference! All signal listening functions complete normally, and then the process exits smoothly.