go-zero
go-zero copied to clipboard
How to make gracefulStop waiting?
the code is generated by goctl, and just added test() function.
func main() {
flag.Parse()
var c config.Config
conf.MustLoad(*configFile, &c)
server := rest.MustNewServer(c.RestConf)
defer server.Stop()
ctx := svc.NewServiceContext(c)
handler.RegisterHandlers(server, ctx)
test()
fmt.Printf("Starting server at %s:%d...\n", c.Host, c.Port)
server.Start()
}
func test() {
proc.SetTimeToForceQuit(time.Minute)
proc.AddWrapUpListener(func() {
fmt.Println("wrap up start...")
time.Sleep(5 * time.Second)
fmt.Println("wrap up done")
})
build and run it in LinuxοΌthen send SIGNTERM, it print log
root@VM-0-16-debian:~# ./demo2 -f demo2-api.yaml
Starting server at 0.0.0.0:8888...
{"@timestamp":"2024-04-21T18:38:06.608+08:00","caller":"proc/shutdown.go:58","content":"Got signal 15, shutting down...","level":"info"}
wrap up start...
{"@timestamp":"2024-04-21T18:38:07.609+08:00","caller":"stat/metrics.go:210","content":"(demo2-api) - qps: 0.0/s, drops: 0, avg time: 0.0ms, med: 0.0ms, 90th: 0.0ms, 99th: 0.0ms, 99.9th: 0.0ms","level":"stat"}
Why it does not wait the listener's func done? How to make it wait?
func signalHandler() {
// signal handler
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGHUP, syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT)
for {
s := <-c
switch s {
case syscall.SIGQUIT, syscall.SIGTERM, syscall.SIGINT:
// do what you want
return
case syscall.SIGHUP:
default:
return
}
}
}
demo repo: https://github.com/jaronnie/jzero/blob/main/daemon/daemon.go
Bot detected the issue body's language is not English, translate it automatically. π―ππ»π§βπ€βπ§π«π§πΏβπ€βπ§π»π©πΎβπ€βπ¨πΏπ¬πΏ
But report: https://gityub. Kom/jaron-ie/jzero/bb/main/daemon/daemon. Go
go-zero already has this logic, but the function 'gracefulStop' did not execute as expected.
core/proc/signals.go
func init() {
go func() {
// https://golang.org/pkg/os/signal/#Notify
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGUSR1, syscall.SIGUSR2, syscall.SIGTERM, syscall.SIGINT)
for {
v := <-signals
switch v {
case syscall.SIGUSR1:
dumpGoroutines(fileCreator{})
case syscall.SIGUSR2:
profiler := StartProfile()
time.AfterFunc(profileDuration, profiler.Stop)
case syscall.SIGTERM:
stopOnSignal()
gracefulStop(signals, syscall.SIGTERM)
case syscall.SIGINT:
stopOnSignal()
gracefulStop(signals, syscall.SIGINT)
default:
logx.Error("Got unregistered signal:", v)
}
}
}()
}
waitForCalled := proc.AddWrapUpListener(func() {
fmt.Println("wrap up start...")
time.Sleep(5 * time.Second)
fmt.Println("wrap up done")
})
waitForCalled()
waitForCalled := proc.AddWrapUpListener(func() { fmt.Println("wrap up start...") time.Sleep(5 * time.Second) fmt.Println("wrap up done") }) waitForCalled()
waitForCalled() will block the flow, before server.Start()
waitForCalled := proc.AddWrapUpListener(func() { fmt.Println("wrap up start...") time.Sleep(5 * time.Second) fmt.Println("wrap up done") }) waitForCalled()waitForCalled() will block the flow, before
server.Start()
Call it after server started.
server.Start() will block the main thread.
gracefulStop does not wait when i run test() in a new goroutine.