From 02becf9e7cd0eb9f2e80ddf65cf82b856759d091 Mon Sep 17 00:00:00 2001 From: "mergify[bot]" <37929162+mergify[bot]@users.noreply.github.com> Date: Mon, 25 Apr 2022 10:19:09 -0400 Subject: [PATCH] fix: data race issues with api.Server (backport #11724) (#11749) --- CHANGELOG.md | 1 + server/api/server.go | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index ef0dc0a3178f..fe48bd636b7c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -211,6 +211,7 @@ Ref: https://keepachangelog.com/en/1.0.0/ ### Bug Fixes +* [\#11724](https://github.com/cosmos/cosmos-sdk/pull/11724) Fix data race issues with `api.Server`. * [\#11354](https://github.com/cosmos/cosmos-sdk/pull/11355) Added missing pagination flag for `bank q total` query. * [\#11197](https://github.com/cosmos/cosmos-sdk/pull/11197) Signing with multisig now works with multisig address which is not in the keyring. * (makefile) [\#11285](https://github.com/cosmos/cosmos-sdk/pull/11285) Fix lint-fix make target. diff --git a/server/api/server.go b/server/api/server.go index 18daefb83c8c..c052c03f52ca 100644 --- a/server/api/server.go +++ b/server/api/server.go @@ -5,6 +5,7 @@ import ( "net" "net/http" "strings" + "sync" "time" "github.com/gogo/gateway" @@ -30,8 +31,13 @@ type Server struct { GRPCGatewayRouter *runtime.ServeMux ClientCtx client.Context - logger log.Logger - metrics *telemetry.Metrics + logger log.Logger + metrics *telemetry.Metrics + // Start() is blocking and generally called from a separate goroutine. + // Close() can be called asynchronously and access shared memory + // via the listener. Therefore, we sync access to Start and Close with + // this mutex to avoid data races. + mtx sync.Mutex listener net.Listener } @@ -83,9 +89,11 @@ func New(clientCtx client.Context, logger log.Logger) *Server { // and are delegated to the Tendermint JSON RPC server. The process is // non-blocking, so an external signal handler must be used. func (s *Server) Start(cfg config.Config) error { + s.mtx.Lock() if cfg.Telemetry.Enabled { m, err := telemetry.New(cfg.Telemetry) if err != nil { + s.mtx.Unlock() return err } @@ -101,6 +109,7 @@ func (s *Server) Start(cfg config.Config) error { listener, err := tmrpcserver.Listen(cfg.API.Address, tmCfg.MaxOpenConnections) if err != nil { + s.mtx.Unlock() return err } @@ -111,15 +120,19 @@ func (s *Server) Start(cfg config.Config) error { if cfg.API.EnableUnsafeCORS { allowAllCORS := handlers.CORS(handlers.AllowedHeaders([]string{"Content-Type"})) + s.mtx.Unlock() return tmrpcserver.Serve(s.listener, allowAllCORS(h), s.logger, tmCfg) } s.logger.Info("starting API server...") + s.mtx.Unlock() return tmrpcserver.Serve(s.listener, s.Router, s.logger, tmCfg) } // Close closes the API server. func (s *Server) Close() error { + s.mtx.Lock() + defer s.mtx.Unlock() return s.listener.Close() }