From 33a19dabd79f62d291d859547d6912336c5ea0cf Mon Sep 17 00:00:00 2001 From: Anton Kaliaev Date: Wed, 22 Apr 2020 15:42:45 +0400 Subject: [PATCH] abci/server: print panic & stack trace to STDERR if logger is not set Closes #4382 --- CHANGELOG_PENDING.md | 1 + abci/server/grpc_server.go | 13 ++++++------ abci/server/socket_server.go | 38 ++++++++++++++++++++++++------------ 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index b48028e4a..2dd0c2e79 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -23,6 +23,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi ### IMPROVEMENTS: +- [abci/server] [\#4719](https://github.com/tendermint/tendermint/pull/4719) Print panic & stack trace to STDERR if logger is not set (@melekes) - [txindex] [\#4466](https://github.com/tendermint/tendermint/pull/4466) Allow to index an event at runtime (@favadi) diff --git a/abci/server/grpc_server.go b/abci/server/grpc_server.go index b953c404d..0f74a34aa 100644 --- a/abci/server/grpc_server.go +++ b/abci/server/grpc_server.go @@ -34,25 +34,24 @@ func NewGRPCServer(protoAddr string, app types.ABCIApplicationServer) service.Se return s } -// OnStart starts the gRPC service +// OnStart starts the gRPC service. func (s *GRPCServer) OnStart() error { - if err := s.BaseService.OnStart(); err != nil { - return err - } ln, err := net.Listen(s.proto, s.addr) if err != nil { return err } - s.Logger.Info("Listening", "proto", s.proto, "addr", s.addr) + s.listener = ln s.server = grpc.NewServer() types.RegisterABCIApplicationServer(s.server, s.app) + + s.Logger.Info("Listening", "proto", s.proto, "addr", s.addr) go s.server.Serve(s.listener) + return nil } -// OnStop stops the gRPC server +// OnStop stops the gRPC server. func (s *GRPCServer) OnStop() { - s.BaseService.OnStop() s.server.Stop() } diff --git a/abci/server/socket_server.go b/abci/server/socket_server.go index efb4d94e0..e68d79599 100644 --- a/abci/server/socket_server.go +++ b/abci/server/socket_server.go @@ -5,9 +5,12 @@ import ( "fmt" "io" "net" + "os" + "runtime" "sync" "github.com/tendermint/tendermint/abci/types" + tmlog "github.com/tendermint/tendermint/libs/log" tmnet "github.com/tendermint/tendermint/libs/net" "github.com/tendermint/tendermint/libs/service" ) @@ -16,6 +19,7 @@ import ( type SocketServer struct { service.BaseService + isLoggerSet bool proto string addr string @@ -42,21 +46,24 @@ func NewSocketServer(protoAddr string, app types.Application) service.Service { return s } +func (s *SocketServer) SetLogger(l tmlog.Logger) { + s.BaseService.SetLogger(l) + s.isLoggerSet = true +} + func (s *SocketServer) OnStart() error { - if err := s.BaseService.OnStart(); err != nil { - return err - } ln, err := net.Listen(s.proto, s.addr) if err != nil { return err } + s.listener = ln go s.acceptConnectionsRoutine() + return nil } func (s *SocketServer) OnStop() { - s.BaseService.OnStop() if err := s.listener.Close(); err != nil { s.Logger.Error("Error closing listener", "err", err) } @@ -105,7 +112,7 @@ func (s *SocketServer) acceptConnectionsRoutine() { if !s.IsRunning() { return // Ignore error from listener closing. } - s.Logger.Error("Failed to accept connection: " + err.Error()) + s.Logger.Error("Failed to accept connection", "err", err) continue } @@ -132,15 +139,15 @@ func (s *SocketServer) waitForClose(closeConn chan error, connID int) { case err == io.EOF: s.Logger.Error("Connection was closed by client") case err != nil: - s.Logger.Error("Connection error", "error", err) + s.Logger.Error("Connection error", "err", err) default: // never happens - s.Logger.Error("Connection was closed.") + s.Logger.Error("Connection was closed") } // Close the connection if err := s.rmConn(connID); err != nil { - s.Logger.Error("Error in closing connection", "error", err) + s.Logger.Error("Error closing connection", "err", err) } } @@ -153,7 +160,14 @@ func (s *SocketServer) handleRequests(closeConn chan error, conn io.Reader, resp // make sure to recover from any app-related panics to allow proper socket cleanup r := recover() if r != nil { - closeConn <- fmt.Errorf("recovered from panic: %v", r) + const size = 64 << 10 + buf := make([]byte, size) + buf = buf[:runtime.Stack(buf, false)] + err := fmt.Errorf("recovered from panic: %v\n%s", r, buf) + if !s.isLoggerSet { + fmt.Fprintln(os.Stderr, err) + } + closeConn <- err s.appMtx.Unlock() } }() @@ -166,7 +180,7 @@ func (s *SocketServer) handleRequests(closeConn chan error, conn io.Reader, resp if err == io.EOF { closeConn <- err } else { - closeConn <- fmt.Errorf("error reading message: %v", err) + closeConn <- fmt.Errorf("error reading message: %w", err) } return } @@ -223,13 +237,13 @@ func (s *SocketServer) handleResponses(closeConn chan error, conn io.Writer, res var res = <-responses err := types.WriteMessage(res, bufWriter) if err != nil { - closeConn <- fmt.Errorf("error writing message: %v", err.Error()) + closeConn <- fmt.Errorf("error writing message: %w", err) return } if _, ok := res.Value.(*types.Response_Flush); ok { err = bufWriter.Flush() if err != nil { - closeConn <- fmt.Errorf("error flushing write buffer: %v", err.Error()) + closeConn <- fmt.Errorf("error flushing write buffer: %w", err) return } }