mirror of
https://github.com/kaspanet/kaspad.git
synced 2025-06-04 13:16:43 +00:00
[NOD-806] Exit early after panic (#650)
* [NOD-806] After panic, gracefully stop logs, and then exit immediately * [NOD-806] Convert non-kaspad applications to use the new spawn * [NOD-806] Fix disabled log at rpcclient * [NOD-806] Refactor HandlePanic * [NOD-806] Cancel Logger interface * [NOD-806] Remove redundant spawn checks from waitgroup_test.go * [NOD-806] Use caller subsystem when logging panics * [NOD-806] Fix go vet errors
This commit is contained in:
parent
606cd668ff
commit
5a99e4d2f3
@ -717,11 +717,7 @@ func (a *AddrManager) Start() {
|
||||
|
||||
// Start the address ticker to save addresses periodically.
|
||||
a.wg.Add(1)
|
||||
spawn(a.addressHandler, a.handlePanic)
|
||||
}
|
||||
|
||||
func (a *AddrManager) handlePanic() {
|
||||
atomic.AddInt32(&a.shutdown, 1)
|
||||
spawn(a.addressHandler)
|
||||
}
|
||||
|
||||
// Stop gracefully shuts down the address manager by stopping the main handler.
|
||||
|
@ -10,4 +10,4 @@ import (
|
||||
)
|
||||
|
||||
var log, _ = logger.Get(logger.SubsystemTags.ADXR)
|
||||
var spawn = panics.GoroutineWrapperFuncWithPanicHandler(log)
|
||||
var spawn = panics.GoroutineWrapperFunc(log)
|
||||
|
@ -23,7 +23,7 @@ const (
|
||||
|
||||
var (
|
||||
cfg *ConfigFlags
|
||||
log logs.Logger
|
||||
log *logs.Logger
|
||||
spawn func(func())
|
||||
)
|
||||
|
||||
|
@ -28,7 +28,5 @@ func initLog(logFile, errLogFile string) {
|
||||
}
|
||||
|
||||
func enableRPCLogging() {
|
||||
rpclog := backendLog.Logger("RPCC")
|
||||
rpclog.SetLevel(logs.LevelTrace)
|
||||
rpcclient.UseLogger(rpclog)
|
||||
rpcclient.UseLogger(backendLog, logs.LevelTrace)
|
||||
}
|
||||
|
@ -12,7 +12,7 @@ import (
|
||||
)
|
||||
|
||||
func main() {
|
||||
defer panics.HandlePanic(log, nil, nil)
|
||||
defer panics.HandlePanic(log, nil)
|
||||
interrupt := signal.InterruptListener()
|
||||
|
||||
cfg, err := parseConfig()
|
||||
|
@ -234,7 +234,7 @@ func (cm *ConnManager) handleFailedConn(c *ConnReq, err error) {
|
||||
}
|
||||
spawnAfter(d, func() {
|
||||
cm.Connect(c)
|
||||
}, nil)
|
||||
})
|
||||
} else if cm.cfg.GetNewAddress != nil {
|
||||
cm.failedAttempts++
|
||||
if cm.failedAttempts >= maxFailedAttempts {
|
||||
@ -243,9 +243,9 @@ func (cm *ConnManager) handleFailedConn(c *ConnReq, err error) {
|
||||
"-- retrying further connections every %s", maxFailedAttempts,
|
||||
cm.cfg.RetryDuration)
|
||||
}
|
||||
spawnAfter(cm.cfg.RetryDuration, cm.NewConnReq, cm.handlePanic)
|
||||
spawnAfter(cm.cfg.RetryDuration, cm.NewConnReq)
|
||||
} else {
|
||||
spawn(cm.NewConnReq, cm.handlePanic)
|
||||
spawn(cm.NewConnReq)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -377,7 +377,7 @@ out:
|
||||
if cm.cfg.OnDisconnection != nil {
|
||||
spawn(func() {
|
||||
cm.cfg.OnDisconnection(connReq)
|
||||
}, cm.handlePanic)
|
||||
})
|
||||
}
|
||||
|
||||
// All internal state has been cleaned up, if
|
||||
@ -576,7 +576,7 @@ func (cm *ConnManager) listenHandler(listener net.Listener) {
|
||||
}
|
||||
spawn(func() {
|
||||
cm.cfg.OnAccept(conn)
|
||||
}, cm.handlePanic)
|
||||
})
|
||||
}
|
||||
|
||||
cm.wg.Done()
|
||||
@ -592,7 +592,7 @@ func (cm *ConnManager) Start() {
|
||||
|
||||
log.Trace("Connection manager started")
|
||||
cm.wg.Add(1)
|
||||
spawn(cm.connHandler, cm.handlePanic)
|
||||
spawn(cm.connHandler)
|
||||
|
||||
// Start all the listeners so long as the caller requested them and
|
||||
// provided a callback to be invoked when connections are accepted.
|
||||
@ -604,12 +604,12 @@ func (cm *ConnManager) Start() {
|
||||
cm.wg.Add(1)
|
||||
spawn(func() {
|
||||
cm.listenHandler(listenerCopy)
|
||||
}, cm.handlePanic)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
for i := atomic.LoadUint64(&cm.connReqCount); i < uint64(cm.cfg.TargetOutbound); i++ {
|
||||
spawn(cm.NewConnReq, cm.handlePanic)
|
||||
spawn(cm.NewConnReq)
|
||||
}
|
||||
}
|
||||
|
||||
@ -618,10 +618,6 @@ func (cm *ConnManager) Wait() {
|
||||
cm.wg.Wait()
|
||||
}
|
||||
|
||||
func (cm *ConnManager) handlePanic() {
|
||||
atomic.AddInt32(&cm.stop, 1)
|
||||
}
|
||||
|
||||
// Stop gracefully shuts down the connection manager.
|
||||
func (cm *ConnManager) Stop() {
|
||||
if atomic.AddInt32(&cm.stop, 1) != 1 {
|
||||
|
@ -10,5 +10,5 @@ import (
|
||||
)
|
||||
|
||||
var log, _ = logger.Get(logger.SubsystemTags.CMGR)
|
||||
var spawn = panics.GoroutineWrapperFuncWithPanicHandler(log)
|
||||
var spawnAfter = panics.AfterFuncWrapperFuncWithPanicHandler(log)
|
||||
var spawn = panics.GoroutineWrapperFunc(log)
|
||||
var spawnAfter = panics.AfterFuncWrapperFunc(log)
|
||||
|
@ -94,6 +94,6 @@ func SeedFromDNS(dagParams *dagconfig.Params, reqServices wire.ServiceFlag, incl
|
||||
}
|
||||
|
||||
seedFn(addresses)
|
||||
}, nil)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ const (
|
||||
)
|
||||
|
||||
var (
|
||||
log logs.Logger
|
||||
log *logs.Logger
|
||||
spawn func(func())
|
||||
shutdownChannel = make(chan error)
|
||||
)
|
||||
|
@ -59,7 +59,7 @@ func kaspadMain(serverChan chan<- *server.Server) error {
|
||||
return err
|
||||
}
|
||||
cfg = config.ActiveConfig()
|
||||
defer panics.HandlePanic(kasdLog, nil, nil)
|
||||
defer panics.HandlePanic(kasdLog, nil)
|
||||
|
||||
// Get a channel that will be closed when a shutdown signal has been
|
||||
// triggered either from an OS signal such as SIGINT (Ctrl+C) or from
|
||||
|
@ -87,7 +87,7 @@ var SubsystemTags = struct {
|
||||
}
|
||||
|
||||
// subsystemLoggers maps each subsystem identifier to its associated logger.
|
||||
var subsystemLoggers = map[string]logs.Logger{
|
||||
var subsystemLoggers = map[string]*logs.Logger{
|
||||
SubsystemTags.ADXR: adxrLog,
|
||||
SubsystemTags.AMGR: amgrLog,
|
||||
SubsystemTags.CMGR: cmgrLog,
|
||||
@ -180,7 +180,7 @@ func SupportedSubsystems() []string {
|
||||
}
|
||||
|
||||
// Get returns a logger of a specific sub system
|
||||
func Get(tag string) (logger logs.Logger, ok bool) {
|
||||
func Get(tag string) (logger *logs.Logger, ok bool) {
|
||||
logger, ok = subsystemLoggers[tag]
|
||||
return
|
||||
}
|
||||
|
@ -1,64 +0,0 @@
|
||||
// Copyright (c) 2013-2017 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package logs
|
||||
|
||||
// Logger is an interface which describes a level-based logger. A default
|
||||
// implementation of Logger is implemented by this package and can be created
|
||||
// by calling (*Backend).Logger.
|
||||
type Logger interface {
|
||||
// Tracef formats message according to format specifier and writes to
|
||||
// to log with LevelTrace.
|
||||
Tracef(format string, params ...interface{})
|
||||
|
||||
// Debugf formats message according to format specifier and writes to
|
||||
// log with LevelDebug.
|
||||
Debugf(format string, params ...interface{})
|
||||
|
||||
// Infof formats message according to format specifier and writes to
|
||||
// log with LevelInfo.
|
||||
Infof(format string, params ...interface{})
|
||||
|
||||
// Warnf formats message according to format specifier and writes to
|
||||
// to log with LevelWarn.
|
||||
Warnf(format string, params ...interface{})
|
||||
|
||||
// Errorf formats message according to format specifier and writes to
|
||||
// to log with LevelError.
|
||||
Errorf(format string, params ...interface{})
|
||||
|
||||
// Criticalf formats message according to format specifier and writes to
|
||||
// log with LevelCritical.
|
||||
Criticalf(format string, params ...interface{})
|
||||
|
||||
// Trace formats message using the default formats for its operands
|
||||
// and writes to log with LevelTrace.
|
||||
Trace(v ...interface{})
|
||||
|
||||
// Debug formats message using the default formats for its operands
|
||||
// and writes to log with LevelDebug.
|
||||
Debug(v ...interface{})
|
||||
|
||||
// Info formats message using the default formats for its operands
|
||||
// and writes to log with LevelInfo.
|
||||
Info(v ...interface{})
|
||||
|
||||
// Warn formats message using the default formats for its operands
|
||||
// and writes to log with LevelWarn.
|
||||
Warn(v ...interface{})
|
||||
|
||||
// Error formats message using the default formats for its operands
|
||||
// and writes to log with LevelError.
|
||||
Error(v ...interface{})
|
||||
|
||||
// Critical formats message using the default formats for its operands
|
||||
// and writes to log with LevelCritical.
|
||||
Critical(v ...interface{})
|
||||
|
||||
// Level returns the current logging level.
|
||||
Level() Level
|
||||
|
||||
// SetLevel changes the logging level to the passed level.
|
||||
SetLevel(level Level)
|
||||
}
|
72
logs/logs.go
72
logs/logs.go
@ -354,12 +354,12 @@ func (b *Backend) Close() {
|
||||
// Logger returns a new logger for a particular subsystem that writes to the
|
||||
// Backend b. A tag describes the subsystem and is included in all log
|
||||
// messages. The logger uses the info verbosity level by default.
|
||||
func (b *Backend) Logger(subsystemTag string) Logger {
|
||||
return &slog{LevelInfo, subsystemTag, b}
|
||||
func (b *Backend) Logger(subsystemTag string) *Logger {
|
||||
return &Logger{LevelInfo, subsystemTag, b}
|
||||
}
|
||||
|
||||
// slog is a subsystem logger for a Backend. Implements the Logger interface.
|
||||
type slog struct {
|
||||
// Logger is a subsystem logger for a Backend.
|
||||
type Logger struct {
|
||||
lvl Level // atomic
|
||||
tag string
|
||||
b *Backend
|
||||
@ -367,9 +367,7 @@ type slog struct {
|
||||
|
||||
// Trace formats message using the default formats for its operands, prepends
|
||||
// the prefix as necessary, and writes to log with LevelTrace.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Trace(args ...interface{}) {
|
||||
func (l *Logger) Trace(args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelTrace {
|
||||
l.b.print(LevelTrace, l.tag, args...)
|
||||
@ -378,9 +376,7 @@ func (l *slog) Trace(args ...interface{}) {
|
||||
|
||||
// Tracef formats message according to format specifier, prepends the prefix as
|
||||
// necessary, and writes to log with LevelTrace.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Tracef(format string, args ...interface{}) {
|
||||
func (l *Logger) Tracef(format string, args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelTrace {
|
||||
l.b.printf(LevelTrace, l.tag, format, args...)
|
||||
@ -389,9 +385,7 @@ func (l *slog) Tracef(format string, args ...interface{}) {
|
||||
|
||||
// Debug formats message using the default formats for its operands, prepends
|
||||
// the prefix as necessary, and writes to log with LevelDebug.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Debug(args ...interface{}) {
|
||||
func (l *Logger) Debug(args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelDebug {
|
||||
l.b.print(LevelDebug, l.tag, args...)
|
||||
@ -400,9 +394,7 @@ func (l *slog) Debug(args ...interface{}) {
|
||||
|
||||
// Debugf formats message according to format specifier, prepends the prefix as
|
||||
// necessary, and writes to log with LevelDebug.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Debugf(format string, args ...interface{}) {
|
||||
func (l *Logger) Debugf(format string, args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelDebug {
|
||||
l.b.printf(LevelDebug, l.tag, format, args...)
|
||||
@ -411,9 +403,7 @@ func (l *slog) Debugf(format string, args ...interface{}) {
|
||||
|
||||
// Info formats message using the default formats for its operands, prepends
|
||||
// the prefix as necessary, and writes to log with LevelInfo.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Info(args ...interface{}) {
|
||||
func (l *Logger) Info(args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelInfo {
|
||||
l.b.print(LevelInfo, l.tag, args...)
|
||||
@ -422,9 +412,7 @@ func (l *slog) Info(args ...interface{}) {
|
||||
|
||||
// Infof formats message according to format specifier, prepends the prefix as
|
||||
// necessary, and writes to log with LevelInfo.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Infof(format string, args ...interface{}) {
|
||||
func (l *Logger) Infof(format string, args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelInfo {
|
||||
l.b.printf(LevelInfo, l.tag, format, args...)
|
||||
@ -433,9 +421,7 @@ func (l *slog) Infof(format string, args ...interface{}) {
|
||||
|
||||
// Warn formats message using the default formats for its operands, prepends
|
||||
// the prefix as necessary, and writes to log with LevelWarn.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Warn(args ...interface{}) {
|
||||
func (l *Logger) Warn(args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelWarn {
|
||||
l.b.print(LevelWarn, l.tag, args...)
|
||||
@ -444,9 +430,7 @@ func (l *slog) Warn(args ...interface{}) {
|
||||
|
||||
// Warnf formats message according to format specifier, prepends the prefix as
|
||||
// necessary, and writes to log with LevelWarn.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Warnf(format string, args ...interface{}) {
|
||||
func (l *Logger) Warnf(format string, args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelWarn {
|
||||
l.b.printf(LevelWarn, l.tag, format, args...)
|
||||
@ -455,9 +439,7 @@ func (l *slog) Warnf(format string, args ...interface{}) {
|
||||
|
||||
// Error formats message using the default formats for its operands, prepends
|
||||
// the prefix as necessary, and writes to log with LevelError.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Error(args ...interface{}) {
|
||||
func (l *Logger) Error(args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelError {
|
||||
l.b.print(LevelError, l.tag, args...)
|
||||
@ -466,9 +448,7 @@ func (l *slog) Error(args ...interface{}) {
|
||||
|
||||
// Errorf formats message according to format specifier, prepends the prefix as
|
||||
// necessary, and writes to log with LevelError.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Errorf(format string, args ...interface{}) {
|
||||
func (l *Logger) Errorf(format string, args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelError {
|
||||
l.b.printf(LevelError, l.tag, format, args...)
|
||||
@ -477,9 +457,7 @@ func (l *slog) Errorf(format string, args ...interface{}) {
|
||||
|
||||
// Critical formats message using the default formats for its operands, prepends
|
||||
// the prefix as necessary, and writes to log with LevelCritical.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Critical(args ...interface{}) {
|
||||
func (l *Logger) Critical(args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelCritical {
|
||||
l.b.print(LevelCritical, l.tag, args...)
|
||||
@ -488,9 +466,7 @@ func (l *slog) Critical(args ...interface{}) {
|
||||
|
||||
// Criticalf formats message according to format specifier, prepends the prefix
|
||||
// as necessary, and writes to log with LevelCritical.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Criticalf(format string, args ...interface{}) {
|
||||
func (l *Logger) Criticalf(format string, args ...interface{}) {
|
||||
lvl := l.Level()
|
||||
if lvl <= LevelCritical {
|
||||
l.b.printf(LevelCritical, l.tag, format, args...)
|
||||
@ -498,22 +474,16 @@ func (l *slog) Criticalf(format string, args ...interface{}) {
|
||||
}
|
||||
|
||||
// Level returns the current logging level
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) Level() Level {
|
||||
func (l *Logger) Level() Level {
|
||||
return Level(atomic.LoadUint32((*uint32)(&l.lvl)))
|
||||
}
|
||||
|
||||
// SetLevel changes the logging level to the passed level.
|
||||
//
|
||||
// This is part of the Logger interface implementation.
|
||||
func (l *slog) SetLevel(level Level) {
|
||||
func (l *Logger) SetLevel(level Level) {
|
||||
atomic.StoreUint32((*uint32)(&l.lvl), uint32(level))
|
||||
}
|
||||
|
||||
// Disabled is a Logger that will never output anything.
|
||||
var Disabled Logger
|
||||
|
||||
func init() {
|
||||
Disabled = &slog{lvl: LevelOff, b: NewBackend()}
|
||||
// Backend returns the log backend
|
||||
func (l *Logger) Backend() *Backend {
|
||||
return l.b
|
||||
}
|
||||
|
@ -306,7 +306,7 @@ func (g *BlkTmplGenerator) populateTemplateFromCandidates(candidateTxs []*candid
|
||||
txsForBlockTemplate.totalMass += selectedTx.txMass
|
||||
txsForBlockTemplate.totalFees += selectedTx.txDesc.Fee
|
||||
|
||||
log.Tracef("Adding tx %s (feePerKB %.2f)",
|
||||
log.Tracef("Adding tx %s (feePerKB %d)",
|
||||
tx.ID(), selectedTx.txDesc.FeePerKB)
|
||||
|
||||
markCandidateTxForDeletion(selectedTx)
|
||||
|
@ -20,7 +20,7 @@ type blockProgressLogger struct {
|
||||
receivedLogTx int64
|
||||
lastBlockLogTime time.Time
|
||||
|
||||
subsystemLogger logs.Logger
|
||||
subsystemLogger *logs.Logger
|
||||
progressAction string
|
||||
sync.Mutex
|
||||
}
|
||||
@ -29,7 +29,7 @@ type blockProgressLogger struct {
|
||||
// The progress message is templated as follows:
|
||||
// {progressAction} {numProcessed} {blocks|block} in the last {timePeriod}
|
||||
// ({numTxs}, height {lastBlockHeight}, {lastBlockTimeStamp})
|
||||
func newBlockProgressLogger(progressMessage string, logger logs.Logger) *blockProgressLogger {
|
||||
func newBlockProgressLogger(progressMessage string, logger *logs.Logger) *blockProgressLogger {
|
||||
return &blockProgressLogger{
|
||||
lastBlockLogTime: time.Now(),
|
||||
progressAction: progressMessage,
|
||||
|
@ -10,4 +10,4 @@ import (
|
||||
)
|
||||
|
||||
var log, _ = logger.Get(logger.SubsystemTags.SYNC)
|
||||
var spawn = panics.GoroutineWrapperFuncWithPanicHandler(log)
|
||||
var spawn = panics.GoroutineWrapperFunc(log)
|
||||
|
@ -995,7 +995,7 @@ func (sm *SyncManager) handleBlockDAGNotification(notification *blockdag.Notific
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("HandleNewBlock failed to handle block %s", block.Hash()))
|
||||
}
|
||||
}, sm.handlePanic)
|
||||
})
|
||||
|
||||
// Relay if we are current and the block was not just now unorphaned.
|
||||
// Otherwise peers that are current should already know about it
|
||||
@ -1098,11 +1098,7 @@ func (sm *SyncManager) Start() {
|
||||
|
||||
log.Trace("Starting sync manager")
|
||||
sm.wg.Add(1)
|
||||
spawn(sm.messageHandler, sm.handlePanic)
|
||||
}
|
||||
|
||||
func (sm *SyncManager) handlePanic() {
|
||||
atomic.AddInt32(&sm.shutdown, 1)
|
||||
spawn(sm.messageHandler)
|
||||
}
|
||||
|
||||
// Stop gracefully shuts down the sync manager by stopping all asynchronous
|
||||
|
@ -1199,7 +1199,7 @@ out:
|
||||
handlerActive = false
|
||||
|
||||
default:
|
||||
log.Warnf("Unsupported message command %s",
|
||||
log.Warnf("Unsupported message command %d",
|
||||
msg.command)
|
||||
}
|
||||
|
||||
|
@ -12,9 +12,11 @@ import (
|
||||
// log is a logger that is initialized with no output filters. This
|
||||
// means the package will not perform any logging by default until the caller
|
||||
// requests it.
|
||||
var log logs.Logger
|
||||
var log *logs.Logger
|
||||
var spawn func(func())
|
||||
|
||||
const logSubsytem = "RPCC"
|
||||
|
||||
// The default amount of logging is none.
|
||||
func init() {
|
||||
DisableLog()
|
||||
@ -23,12 +25,15 @@ func init() {
|
||||
// DisableLog disables all library log output. Logging output is disabled
|
||||
// by default until UseLogger is called.
|
||||
func DisableLog() {
|
||||
log = logs.Disabled
|
||||
backend := logs.NewBackend()
|
||||
log = backend.Logger(logSubsytem)
|
||||
log.SetLevel(logs.LevelOff)
|
||||
spawn = panics.GoroutineWrapperFunc(log)
|
||||
}
|
||||
|
||||
// UseLogger uses a specified Logger to output package logging info.
|
||||
func UseLogger(logger logs.Logger) {
|
||||
log = logger
|
||||
func UseLogger(backend *logs.Backend, level logs.Level) {
|
||||
log = backend.Logger(logSubsytem)
|
||||
log.SetLevel(level)
|
||||
spawn = panics.GoroutineWrapperFunc(log)
|
||||
}
|
||||
|
@ -21,16 +21,14 @@ func (sp *Peer) OnGetAddr(_ *peer.Peer, msg *wire.MsgGetAddr) {
|
||||
// Do not accept getaddr requests from outbound peers. This reduces
|
||||
// fingerprinting attacks.
|
||||
if !sp.Inbound() {
|
||||
peerLog.Debugf("Ignoring getaddr request from outbound peer ",
|
||||
"%s", sp)
|
||||
peerLog.Debugf("Ignoring getaddr request from outbound peer %s", sp)
|
||||
return
|
||||
}
|
||||
|
||||
// Only allow one getaddr request per connection to discourage
|
||||
// address stamping of inv announcements.
|
||||
if sp.sentAddrs {
|
||||
peerLog.Debugf("Ignoring repeated getaddr request from peer ",
|
||||
"%s", sp)
|
||||
peerLog.Debugf("Ignoring repeated getaddr request from peer %s", sp)
|
||||
return
|
||||
}
|
||||
sp.sentAddrs = true
|
||||
|
@ -13,10 +13,6 @@ import (
|
||||
// subsystems using the same code paths as when an interrupt signal is received.
|
||||
var ShutdownRequestChannel = make(chan struct{})
|
||||
|
||||
// PanicShutdownChannel is used to initiate shutdown when any thread
|
||||
// panics using the same code paths as when an interrupt signal is received.
|
||||
var PanicShutdownChannel = make(chan struct{})
|
||||
|
||||
// interruptSignals defines the default signals to catch in order to do a proper
|
||||
// shutdown. This may be modified during init depending on the platform.
|
||||
var interruptSignals = []os.Signal{os.Interrupt}
|
||||
@ -39,9 +35,6 @@ func InterruptListener() <-chan struct{} {
|
||||
|
||||
case <-ShutdownRequestChannel:
|
||||
kasdLog.Info("Shutdown requested. Shutting down...")
|
||||
|
||||
case <-PanicShutdownChannel:
|
||||
kasdLog.Info("Panic occurred. Shutting down...")
|
||||
}
|
||||
close(c)
|
||||
|
||||
@ -57,11 +50,6 @@ func InterruptListener() <-chan struct{} {
|
||||
case <-ShutdownRequestChannel:
|
||||
kasdLog.Info("Shutdown requested. Already " +
|
||||
"shutting down...")
|
||||
|
||||
case <-PanicShutdownChannel:
|
||||
kasdLog.Info("Panic occurred while shutting down. " +
|
||||
"Forcing shut down...")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
}()
|
||||
|
@ -1,15 +0,0 @@
|
||||
// Copyright (c) 2013-2014 The btcsuite developers
|
||||
// Use of this source code is governed by an ISC
|
||||
// license that can be found in the LICENSE file.
|
||||
|
||||
package locks
|
||||
|
||||
import (
|
||||
"github.com/kaspanet/kaspad/logger"
|
||||
"github.com/kaspanet/kaspad/util/panics"
|
||||
)
|
||||
|
||||
var (
|
||||
log, _ = logger.Get(logger.SubsystemTags.UTIL)
|
||||
spawn = panics.GoroutineWrapperFunc(log)
|
||||
)
|
@ -7,7 +7,6 @@ package locks
|
||||
import (
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
// All of the tests, except TestAddAfterWait and
|
||||
@ -17,29 +16,6 @@ import (
|
||||
// behaves the same, except enabling the use of add()
|
||||
// concurrently with wait()
|
||||
|
||||
func spawnPatch(t *testing.T) (checkIfRunningSpawnsAreLeft func()) {
|
||||
realSpawn := spawn
|
||||
runningSpawns := int32(0)
|
||||
spawn = func(f func()) {
|
||||
atomic.AddInt32(&runningSpawns, 1)
|
||||
realSpawn(func() {
|
||||
f()
|
||||
atomic.AddInt32(&runningSpawns, -1)
|
||||
})
|
||||
}
|
||||
return func() {
|
||||
defer func() {
|
||||
spawn = realSpawn
|
||||
}()
|
||||
if runningSpawns != 0 {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
if runningSpawns != 0 {
|
||||
t.Fatalf("%d running spawns left", runningSpawns)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testWaitGroup(t *testing.T, wg1 *waitGroup, wg2 *waitGroup) {
|
||||
n := int64(16)
|
||||
wg1.add(n)
|
||||
@ -67,8 +43,6 @@ func testWaitGroup(t *testing.T, wg1 *waitGroup, wg2 *waitGroup) {
|
||||
}
|
||||
|
||||
func TestWaitGroup(t *testing.T) {
|
||||
checkIfRunningSpawnsAreLeft := spawnPatch(t)
|
||||
defer checkIfRunningSpawnsAreLeft()
|
||||
wg1 := newWaitGroup()
|
||||
wg2 := newWaitGroup()
|
||||
|
||||
@ -94,8 +68,6 @@ func TestWaitGroupMisuse(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAddAfterWait(t *testing.T) {
|
||||
checkIfRunningSpawnsAreLeft := spawnPatch(t)
|
||||
defer checkIfRunningSpawnsAreLeft()
|
||||
wg := newWaitGroup()
|
||||
wg.add(1)
|
||||
syncChan := make(chan struct{})
|
||||
@ -113,8 +85,6 @@ func TestAddAfterWait(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWaitGroupRace(t *testing.T) {
|
||||
checkIfRunningSpawnsAreLeft := spawnPatch(t)
|
||||
defer checkIfRunningSpawnsAreLeft()
|
||||
// Run this test for about 1ms.
|
||||
for i := 0; i < 1000; i++ {
|
||||
wg := newWaitGroup()
|
||||
@ -141,8 +111,6 @@ func TestWaitGroupRace(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWaitGroupAlign(t *testing.T) {
|
||||
checkIfRunningSpawnsAreLeft := spawnPatch(t)
|
||||
defer checkIfRunningSpawnsAreLeft()
|
||||
type X struct {
|
||||
x byte
|
||||
wg *waitGroup
|
||||
@ -157,8 +125,6 @@ func TestWaitGroupAlign(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestWaitAfterAddDoneCounterHasReset(t *testing.T) {
|
||||
checkIfRunningSpawnsAreLeft := spawnPatch(t)
|
||||
defer checkIfRunningSpawnsAreLeft()
|
||||
wg := newWaitGroup()
|
||||
wg.add(1)
|
||||
wg.done()
|
||||
|
@ -1,69 +1,58 @@
|
||||
package panics
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/kaspanet/kaspad/logs"
|
||||
"github.com/kaspanet/kaspad/signal"
|
||||
"os"
|
||||
"runtime/debug"
|
||||
"time"
|
||||
)
|
||||
|
||||
// HandlePanic recovers panics, log them, runs an optional panicHandler,
|
||||
// and then initiates a clean shutdown.
|
||||
func HandlePanic(log logs.Logger, goroutineStackTrace []byte, panicHandler func()) {
|
||||
if err := recover(); err != nil {
|
||||
func HandlePanic(log *logs.Logger, goroutineStackTrace []byte) {
|
||||
err := recover()
|
||||
if err == nil {
|
||||
return
|
||||
}
|
||||
|
||||
panicHandlerDone := make(chan struct{})
|
||||
go func() {
|
||||
log.Criticalf("Fatal error: %+v", err)
|
||||
if goroutineStackTrace != nil {
|
||||
log.Criticalf("goroutine stack trace: %s", goroutineStackTrace)
|
||||
log.Criticalf("Goroutine stack trace: %s", goroutineStackTrace)
|
||||
}
|
||||
log.Criticalf("Stack trace: %s", debug.Stack())
|
||||
if panicHandler != nil {
|
||||
panicHandler()
|
||||
}
|
||||
signal.PanicShutdownChannel <- struct{}{}
|
||||
log.Backend().Close()
|
||||
panicHandlerDone <- struct{}{}
|
||||
}()
|
||||
|
||||
const panicHandlerTimeout = 5 * time.Second
|
||||
select {
|
||||
case <-time.Tick(panicHandlerTimeout):
|
||||
fmt.Fprintln(os.Stderr, "Couldn't handle a fatal error. Exiting...")
|
||||
case <-panicHandlerDone:
|
||||
}
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// GoroutineWrapperFunc returns a goroutine wrapper function that handles panics and writes them to the log.
|
||||
func GoroutineWrapperFunc(log logs.Logger) func(func()) {
|
||||
func GoroutineWrapperFunc(log *logs.Logger) func(func()) {
|
||||
return func(f func()) {
|
||||
stackTrace := debug.Stack()
|
||||
go func() {
|
||||
defer HandlePanic(log, stackTrace, nil)
|
||||
f()
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// GoroutineWrapperFuncWithPanicHandler returns a goroutine wrapper function that handles panics,
|
||||
// writes them to the log, and executes a handler function for panics.
|
||||
func GoroutineWrapperFuncWithPanicHandler(log logs.Logger) func(func(), func()) {
|
||||
return func(f func(), panicHandler func()) {
|
||||
stackTrace := debug.Stack()
|
||||
go func() {
|
||||
defer HandlePanic(log, stackTrace, panicHandler)
|
||||
defer HandlePanic(log, stackTrace)
|
||||
f()
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
// AfterFuncWrapperFunc returns a time.AfterFunc wrapper function that handles panics.
|
||||
func AfterFuncWrapperFunc(log logs.Logger) func(d time.Duration, f func()) *time.Timer {
|
||||
func AfterFuncWrapperFunc(log *logs.Logger) func(d time.Duration, f func()) *time.Timer {
|
||||
return func(d time.Duration, f func()) *time.Timer {
|
||||
stackTrace := debug.Stack()
|
||||
return time.AfterFunc(d, func() {
|
||||
defer HandlePanic(log, stackTrace, nil)
|
||||
f()
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// AfterFuncWrapperFuncWithPanicHandler returns a time.AfterFunc wrapper function that handles panics,
|
||||
// writes them to the log, and executes a handler function for panics.
|
||||
func AfterFuncWrapperFuncWithPanicHandler(log logs.Logger) func(d time.Duration, f func(), panicHandler func()) *time.Timer {
|
||||
return func(d time.Duration, f func(), panicHandler func()) *time.Timer {
|
||||
stackTrace := debug.Stack()
|
||||
return time.AfterFunc(d, func() {
|
||||
defer HandlePanic(log, stackTrace, panicHandler)
|
||||
defer HandlePanic(log, stackTrace)
|
||||
f()
|
||||
})
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user