2019-10-15 16:39:51 +03:00
// Copyright 2019 The Gitea Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package graceful
import (
"os"
"runtime"
"code.gitea.io/gitea/modules/log"
)
2019-11-21 21:32:02 +03:00
// awaitShutdown waits for the shutdown signal from the Manager
func ( srv * Server ) awaitShutdown ( ) {
select {
2019-12-15 12:51:28 +03:00
case <- GetManager ( ) . IsShutdown ( ) :
2019-11-21 21:32:02 +03:00
// Shutdown
srv . doShutdown ( )
2019-12-15 12:51:28 +03:00
case <- GetManager ( ) . IsHammer ( ) :
2019-11-21 21:32:02 +03:00
// Hammer
srv . doShutdown ( )
srv . doHammer ( )
}
2019-12-15 12:51:28 +03:00
<- GetManager ( ) . IsHammer ( )
2019-11-21 21:32:02 +03:00
srv . doHammer ( )
}
2019-10-15 16:39:51 +03:00
// shutdown closes the listener so that no new connections are accepted
// and starts a goroutine that will hammer (stop all running requests) the server
// after setting.GracefulHammerTime.
2019-11-21 21:32:02 +03:00
func ( srv * Server ) doShutdown ( ) {
2019-10-15 16:39:51 +03:00
// only shutdown if we're running.
if srv . getState ( ) != stateRunning {
return
}
srv . setState ( stateShuttingDown )
if srv . OnShutdown != nil {
srv . OnShutdown ( )
}
err := srv . listener . Close ( )
if err != nil {
log . Error ( "PID: %d Listener.Close() error: %v" , os . Getpid ( ) , err )
} else {
log . Info ( "PID: %d Listener (%s) closed." , os . Getpid ( ) , srv . listener . Addr ( ) )
}
}
2019-11-21 21:32:02 +03:00
func ( srv * Server ) doHammer ( ) {
2019-10-15 16:39:51 +03:00
defer func ( ) {
// We call srv.wg.Done() until it panics.
// This happens if we call Done() when the WaitGroup counter is already at 0
// So if it panics -> we're done, Serve() will return and the
// parent will goroutine will exit.
if r := recover ( ) ; r != nil {
log . Error ( "WaitGroup at 0: Error: %v" , r )
}
} ( )
if srv . getState ( ) != stateShuttingDown {
return
}
log . Warn ( "Forcefully shutting down parent" )
for {
if srv . getState ( ) == stateTerminate {
break
}
srv . wg . Done ( )
// Give other goroutines a chance to finish before we forcibly stop them.
runtime . Gosched ( )
}
}