Avoid unexpected panic in graceful manager (#29629)

There is a fundamental design problem of the "manager" and the "wait
group".
If nothing has started, the "Wait" just panics: sync: WaitGroup is
reused before previous Wait has returned
There is no clear solution besides a complete rewriting of the "manager"

If there are some mistakes in the app.ini, end users would just see the
"panic", but not the real error messages. A real case: #27643

This PR is just a quick fix for the annoying panic problem.

(cherry picked from commit 90a3f2d4b7ed3890d9655c0334444f86d89b7b30)
This commit is contained in:
wxiaoguang 2024-03-06 19:50:39 +08:00 committed by Earl Warren
parent ee4443c998
commit a8f5449cd9
No known key found for this signature in database
GPG key ID: 0579CB2928A78A00
2 changed files with 18 additions and 2 deletions

View file

@ -59,7 +59,15 @@ func (g *Manager) start() {
go func() { go func() {
defer close(startupDone) defer close(startupDone)
// Wait till we're done getting all the listeners and then close the unused ones // Wait till we're done getting all the listeners and then close the unused ones
g.createServerWaitGroup.Wait() func() {
// FIXME: there is a fundamental design problem of the "manager" and the "wait group".
// If nothing has started, the "Wait" just panics: sync: WaitGroup is reused before previous Wait has returned
// There is no clear solution besides a complete rewriting of the "manager"
defer func() {
_ = recover()
}()
g.createServerWaitGroup.Wait()
}()
// Ignore the error here there's not much we can do with it, they're logged in the CloseProvidedListeners function // Ignore the error here there's not much we can do with it, they're logged in the CloseProvidedListeners function
_ = CloseProvidedListeners() _ = CloseProvidedListeners()
g.notify(readyMsg) g.notify(readyMsg)

View file

@ -150,7 +150,15 @@ func (g *Manager) awaitServer(limit time.Duration) bool {
c := make(chan struct{}) c := make(chan struct{})
go func() { go func() {
defer close(c) defer close(c)
g.createServerWaitGroup.Wait() func() {
// FIXME: there is a fundamental design problem of the "manager" and the "wait group".
// If nothing has started, the "Wait" just panics: sync: WaitGroup is reused before previous Wait has returned
// There is no clear solution besides a complete rewriting of the "manager"
defer func() {
_ = recover()
}()
g.createServerWaitGroup.Wait()
}()
}() }()
if limit > 0 { if limit > 0 {
select { select {