cosmos-sdk/stack/recovery.go

82 lines
2.2 KiB
Go
Raw Normal View History

2017-06-29 07:09:15 -07:00
package stack
import (
"fmt"
2017-07-30 14:26:25 -07:00
abci "github.com/tendermint/abci/types"
"github.com/tendermint/tmlibs/log"
2017-06-29 07:09:15 -07:00
"github.com/tendermint/basecoin"
"github.com/tendermint/basecoin/errors"
2017-07-06 05:23:38 -07:00
"github.com/tendermint/basecoin/state"
2017-06-29 07:09:15 -07:00
)
// nolint
2017-06-29 07:09:15 -07:00
const (
NameRecovery = "rcvr"
)
// Recovery catches any panics and returns them as errors instead
type Recovery struct{}
// Name of the module - fulfills Middleware interface
func (Recovery) Name() string {
2017-06-29 07:09:15 -07:00
return NameRecovery
}
var _ Middleware = Recovery{}
// CheckTx catches any panic and converts to error - fulfills Middlware interface
func (Recovery) CheckTx(ctx basecoin.Context, store state.SimpleDB, tx basecoin.Tx, next basecoin.Checker) (res basecoin.CheckResult, err error) {
2017-06-29 07:09:15 -07:00
defer func() {
if r := recover(); r != nil {
err = normalizePanic(r)
}
}()
return next.CheckTx(ctx, store, tx)
}
// DeliverTx catches any panic and converts to error - fulfills Middlware interface
func (Recovery) DeliverTx(ctx basecoin.Context, store state.SimpleDB, tx basecoin.Tx, next basecoin.Deliver) (res basecoin.DeliverResult, err error) {
2017-06-29 07:09:15 -07:00
defer func() {
if r := recover(); r != nil {
err = normalizePanic(r)
}
}()
return next.DeliverTx(ctx, store, tx)
}
2017-07-30 09:57:48 -07:00
// InitState catches any panic and converts to error - fulfills Middlware interface
func (Recovery) InitState(l log.Logger, store state.SimpleDB, module, key, value string, next basecoin.InitStater) (log string, err error) {
defer func() {
if r := recover(); r != nil {
err = normalizePanic(r)
}
}()
2017-07-30 09:57:48 -07:00
return next.InitState(l, store, module, key, value)
}
2017-07-30 14:26:25 -07:00
// InitValidate catches any panic and logs it
// TODO: return an error???
func (Recovery) InitValidate(l log.Logger, store state.SimpleDB,
vals []*abci.Validator, next basecoin.InitValidater) {
defer func() {
if r := recover(); r != nil {
// TODO: return an error???
err := normalizePanic(r)
l.With("err", err).Error(err.Error())
}
}()
next.InitValidate(l, store, vals)
}
2017-06-29 07:09:15 -07:00
// normalizePanic makes sure we can get a nice TMError (with stack) out of it
func normalizePanic(p interface{}) error {
if err, isErr := p.(error); isErr {
return errors.Wrap(err)
}
msg := fmt.Sprintf("%v", p)
2017-07-03 05:50:33 -07:00
return errors.ErrInternal(msg)
2017-06-29 07:09:15 -07:00
}