3
0
mirror of https://github.com/ergochat/ergo.git synced 2024-11-15 00:19:29 +01:00
Provide a nondestructive stack trace dump option even when the http pprof
listener is disabled
This commit is contained in:
Shivaram Lingamneni 2022-12-11 00:53:12 -05:00
parent 77de026961
commit d17faf6bcb
3 changed files with 28 additions and 5 deletions

View File

@ -12,6 +12,7 @@ import (
_ "net/http/pprof" _ "net/http/pprof"
"os" "os"
"os/signal" "os/signal"
"runtime/pprof"
"strconv" "strconv"
"strings" "strings"
"sync" "sync"
@ -83,6 +84,7 @@ type Server struct {
rehashSignal chan os.Signal rehashSignal chan os.Signal
pprofServer *http.Server pprofServer *http.Server
exitSignals chan os.Signal exitSignals chan os.Signal
tracebackSignal chan os.Signal
snomasks SnoManager snomasks SnoManager
store *buntdb.DB store *buntdb.DB
historyDB mysql.MySQL historyDB mysql.MySQL
@ -98,11 +100,12 @@ type Server struct {
func NewServer(config *Config, logger *logger.Manager) (*Server, error) { func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
// initialize data structures // initialize data structures
server := &Server{ server := &Server{
ctime: time.Now().UTC(), ctime: time.Now().UTC(),
listeners: make(map[string]IRCListener), listeners: make(map[string]IRCListener),
logger: logger, logger: logger,
rehashSignal: make(chan os.Signal, 1), rehashSignal: make(chan os.Signal, 1),
exitSignals: make(chan os.Signal, len(utils.ServerExitSignals)), exitSignals: make(chan os.Signal, len(utils.ServerExitSignals)),
tracebackSignal: make(chan os.Signal, len(utils.ServerTracebackSignals)),
} }
server.defcon.Store(5) server.defcon.Store(5)
@ -120,6 +123,9 @@ func NewServer(config *Config, logger *logger.Manager) (*Server, error) {
// Attempt to clean up when receiving these signals. // Attempt to clean up when receiving these signals.
signal.Notify(server.exitSignals, utils.ServerExitSignals...) signal.Notify(server.exitSignals, utils.ServerExitSignals...)
signal.Notify(server.rehashSignal, syscall.SIGHUP) signal.Notify(server.rehashSignal, syscall.SIGHUP)
if len(utils.ServerTracebackSignals) != 0 {
signal.Notify(server.tracebackSignal, utils.ServerTracebackSignals...)
}
time.AfterFunc(alwaysOnMaintenanceInterval, server.periodicAlwaysOnMaintenance) time.AfterFunc(alwaysOnMaintenanceInterval, server.periodicAlwaysOnMaintenance)
@ -158,6 +164,8 @@ func (server *Server) Run() {
case <-server.rehashSignal: case <-server.rehashSignal:
server.logger.Info("server", "Rehashing due to SIGHUP") server.logger.Info("server", "Rehashing due to SIGHUP")
go server.rehash() go server.rehash()
case <-server.tracebackSignal:
go server.dumpStacks()
} }
} }
} }
@ -1128,3 +1136,11 @@ var (
Edmund Huber, edmund-huber Edmund Huber, edmund-huber
`, "\n") `, "\n")
) )
func (server *Server) dumpStacks() {
if gprof := pprof.Lookup("goroutine"); gprof != nil {
gprof.WriteTo(os.Stderr, 2)
} else {
server.logger.Error("internal", "unable to dump goroutine stacks")
}
}

View File

@ -18,4 +18,8 @@ var (
syscall.SIGTERM, syscall.SIGTERM,
syscall.SIGQUIT, syscall.SIGQUIT,
} }
ServerTracebackSignals = []os.Signal{
syscall.SIGUSR1,
}
) )

View File

@ -18,4 +18,7 @@ var (
syscall.SIGINT, syscall.SIGINT,
syscall.SIGTERM, syscall.SIGTERM,
} }
// no SIGUSR1 on plan9
ServerTracebackSignals []os.Signal
) )