Fixed double closing of closeNotify channel which could happen during shutdown

This commit is contained in:
Ni Rui
2022-09-15 17:10:50 +08:00
parent ff3131ef63
commit 7a5dc076ff

View File

@@ -100,8 +100,18 @@ func (a Application) run(
} }
closeNotify := closeSigBuilder() closeNotify := closeSigBuilder()
closeNotifyDisableLock := sync.Mutex{}
signal.Notify(closeNotify, os.Kill, os.Interrupt, syscall.SIGHUP) signal.Notify(closeNotify, os.Kill, os.Interrupt, syscall.SIGHUP)
defer signal.Stop(closeNotify) defer func() {
closeNotifyDisableLock.Lock()
defer closeNotifyDisableLock.Unlock()
if closeNotify == nil {
return
}
signal.Stop(closeNotify)
close(closeNotify)
closeNotify = nil
}()
servers := make([]*server.Serving, 0, len(c.Servers)) servers := make([]*server.Serving, 0, len(c.Servers))
s := server.New(a.logger) s := server.New(a.logger)
@@ -110,47 +120,37 @@ func (a Application) run(
for i := len(servers); i > 0; i-- { for i := len(servers); i > 0; i-- {
servers[i-1].Close() servers[i-1].Close()
} }
s.Wait() s.Wait()
}() }()
closeNotifyDisableLock := sync.Mutex{}
for _, ss := range c.Servers { for _, ss := range c.Servers {
newServer := s.Serve(c.Common(), ss, func(e error) { newServer := s.Serve(c.Common(), ss, func(e error) {
closeNotifyDisableLock.Lock() closeNotifyDisableLock.Lock()
defer closeNotifyDisableLock.Unlock() defer closeNotifyDisableLock.Unlock()
if closeNotify == nil { if closeNotify == nil {
return return
} }
err = e err = e
signal.Stop(closeNotify)
close(closeNotify) close(closeNotify)
closeNotify = nil closeNotify = nil
}, handlerBuilder(commands)) }, handlerBuilder(commands))
servers = append(servers, newServer) servers = append(servers, newServer)
} }
switch <-closeNotify { switch <-closeNotify {
case syscall.SIGHUP: case syscall.SIGHUP:
return true, nil return true, nil
case syscall.SIGTERM: case syscall.SIGTERM:
fallthrough fallthrough
case os.Kill: case os.Kill:
fallthrough fallthrough
case os.Interrupt: case os.Interrupt:
a.screen.Write(screenLineWipper) a.screen.Write(screenLineWipper)
return false, nil return false, nil
default: default:
closeNotifyDisableLock.Lock() closeNotifyDisableLock.Lock()
defer closeNotifyDisableLock.Unlock() defer closeNotifyDisableLock.Unlock()
return false, err return false, err
} }
} }