From 2ac5a559b4c88385e173b673d1f6250ff7c55263 Mon Sep 17 00:00:00 2001 From: Marko Date: Mon, 20 Jul 2020 09:55:09 +0200 Subject: [PATCH] libs: wrap mutexes for build flag with godeadlock (#5126) ## Description This PR wraps the stdlib sync.(RW)Mutex & godeadlock.(RW)Mutex. This enables using go-deadlock via a build flag instead of using sed to replace sync with godeadlock in all files Closes: #3242 --- CHANGELOG_PENDING.md | 1 + abci/client/client.go | 3 ++- abci/client/grpc_client.go | 4 ++-- abci/client/local_client.go | 9 ++++---- abci/client/socket_client.go | 4 ++-- abci/server/socket_server.go | 6 ++--- behaviour/reporter.go | 4 ++-- blockchain/v0/pool.go | 7 +++--- blockchain/v2/reactor.go | 4 ++-- consensus/common_test.go | 5 +++-- consensus/reactor.go | 3 ++- consensus/reactor_test.go | 3 ++- consensus/state.go | 4 ++-- go.mod | 2 ++ go.sum | 4 ++++ libs/clist/clist.go | 6 +++-- libs/cmap/cmap.go | 6 +++-- libs/events/events.go | 8 +++---- libs/flowrate/flowrate.go | 5 +++-- libs/json/structs.go | 5 +++-- libs/json/types.go | 5 +++-- libs/pubsub/pubsub.go | 4 ++-- libs/pubsub/subscription.go | 5 +++-- libs/rand/random.go | 5 +++-- libs/sync/deadlock.go | 17 ++++++++++++++ libs/sync/sync.go | 15 +++++++++++++ libs/tempfile/tempfile.go | 5 +++-- libs/timer/throttle_timer.go | 5 +++-- libs/timer/throttle_timer_test.go | 5 +++-- light/client.go | 4 ++-- light/store/db/db.go | 4 ++-- mempool/clist_mempool.go | 5 +++-- mempool/reactor.go | 4 ++-- p2p/conn/connection.go | 4 ++-- p2p/conn/secret_connection.go | 6 ++--- p2p/conn_set.go | 5 +++-- p2p/fuzz.go | 4 ++-- p2p/peer_set.go | 5 +++-- p2p/pex/addrbook.go | 3 ++- p2p/switch_test.go | 4 ++-- p2p/trust/metric.go | 4 ++-- p2p/trust/store.go | 4 ++-- privval/signer_endpoint.go | 4 ++-- privval/signer_listener_endpoint.go | 4 ++-- privval/signer_server.go | 4 ++-- proxy/client.go | 6 ++--- rpc/client/http/http.go | 4 ++-- rpc/jsonrpc/client/http_json_client.go | 6 ++--- rpc/jsonrpc/client/ws_client.go | 3 ++- rpc/jsonrpc/client/ws_client_test.go | 4 ++-- statesync/chunks.go | 4 ++-- statesync/reactor.go | 4 ++-- statesync/snapshots.go | 4 ++-- statesync/stateprovider.go | 10 ++++----- statesync/syncer.go | 4 ++-- statesync/syncer_test.go | 4 ++-- store/store.go | 4 ++-- tests.mk | 31 +++++--------------------- types/block.go | 4 ++-- types/part_set.go | 4 ++-- types/vote_set.go | 4 ++-- 61 files changed, 182 insertions(+), 145 deletions(-) create mode 100644 libs/sync/deadlock.go create mode 100644 libs/sync/sync.go diff --git a/CHANGELOG_PENDING.md b/CHANGELOG_PENDING.md index 978e86288..27f447b98 100644 --- a/CHANGELOG_PENDING.md +++ b/CHANGELOG_PENDING.md @@ -117,6 +117,7 @@ Friendly reminder, we have a [bug bounty program](https://hackerone.com/tendermi - [state] [\#4781](https://github.com/tendermint/tendermint/pull/4781) Export `InitStateVersion` for the initial state version (@erikgrinaker) - [txindex] [\#4466](https://github.com/tendermint/tendermint/pull/4466) Allow to index an event at runtime (@favadi) - `abci.EventAttribute` replaces `KV.Pair` +- [libs] \#5126 Add a sync package which wraps sync.(RW)Mutex & deadlock.(RW)Mutex and use a build flag (deadlock) in order to enable deadlock checking - [types] [\#4905](https://github.com/tendermint/tendermint/pull/4905) Add `ValidateBasic` to validator and validator set (@cmwaters) - [rpc] \#4968 JSON encoding is now handled by `libs/json`, not Amino - [mempool] Add RemoveTxByKey() exported function for custom mempool cleaning (@p4u) diff --git a/abci/client/client.go b/abci/client/client.go index b65ce1993..09583327a 100644 --- a/abci/client/client.go +++ b/abci/client/client.go @@ -6,6 +6,7 @@ import ( "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" ) const ( @@ -84,7 +85,7 @@ type ReqRes struct { *sync.WaitGroup *types.Response // Not set atomically, so be sure to use WaitGroup. - mtx sync.Mutex + mtx tmsync.Mutex done bool // Gets set to true once *after* WaitGroup.Done(). cb func(*types.Response) // A single callback that may be set. } diff --git a/abci/client/grpc_client.go b/abci/client/grpc_client.go index 9d8e9ca3a..bb38bf158 100644 --- a/abci/client/grpc_client.go +++ b/abci/client/grpc_client.go @@ -3,7 +3,6 @@ package abcicli import ( "fmt" "net" - "sync" "time" "golang.org/x/net/context" @@ -12,6 +11,7 @@ import ( "github.com/tendermint/tendermint/abci/types" tmnet "github.com/tendermint/tendermint/libs/net" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" ) var _ Client = (*grpcClient)(nil) @@ -25,7 +25,7 @@ type grpcClient struct { client types.ABCIApplicationClient conn *grpc.ClientConn - mtx sync.Mutex + mtx tmsync.Mutex addr string err error resCb func(*types.Request, *types.Response) // listens to all callbacks diff --git a/abci/client/local_client.go b/abci/client/local_client.go index ccd407d07..b3bdc451d 100644 --- a/abci/client/local_client.go +++ b/abci/client/local_client.go @@ -1,10 +1,9 @@ package abcicli import ( - "sync" - types "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" ) var _ Client = (*localClient)(nil) @@ -16,14 +15,14 @@ var _ Client = (*localClient)(nil) type localClient struct { service.BaseService - mtx *sync.Mutex + mtx *tmsync.Mutex types.Application Callback } -func NewLocalClient(mtx *sync.Mutex, app types.Application) Client { +func NewLocalClient(mtx *tmsync.Mutex, app types.Application) Client { if mtx == nil { - mtx = new(sync.Mutex) + mtx = new(tmsync.Mutex) } cli := &localClient{ mtx: mtx, diff --git a/abci/client/socket_client.go b/abci/client/socket_client.go index 4ab38fddc..18ee003d9 100644 --- a/abci/client/socket_client.go +++ b/abci/client/socket_client.go @@ -8,12 +8,12 @@ import ( "io" "net" "reflect" - "sync" "time" "github.com/tendermint/tendermint/abci/types" tmnet "github.com/tendermint/tendermint/libs/net" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/libs/timer" ) @@ -36,7 +36,7 @@ type socketClient struct { reqQueue chan *ReqRes flushTimer *timer.ThrottleTimer - mtx sync.Mutex + mtx tmsync.Mutex err error reqSent *list.List // list of requests sent, waiting for response resCb func(*types.Request, *types.Response) // called on all requests, if set. diff --git a/abci/server/socket_server.go b/abci/server/socket_server.go index 20090b768..3f99a3765 100644 --- a/abci/server/socket_server.go +++ b/abci/server/socket_server.go @@ -7,12 +7,12 @@ import ( "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" + tmsync "github.com/tendermint/tendermint/libs/sync" ) // var maxNumberConnections = 2 @@ -25,11 +25,11 @@ type SocketServer struct { addr string listener net.Listener - connsMtx sync.Mutex + connsMtx tmsync.Mutex conns map[int]net.Conn nextConnID int - appMtx sync.Mutex + appMtx tmsync.Mutex app types.Application } diff --git a/behaviour/reporter.go b/behaviour/reporter.go index 1f16b9bb3..8dc10389e 100644 --- a/behaviour/reporter.go +++ b/behaviour/reporter.go @@ -2,8 +2,8 @@ package behaviour import ( "errors" - "sync" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" ) @@ -50,7 +50,7 @@ func (spbr *SwitchReporter) Report(behaviour PeerBehaviour) error { // interface used in reactor tests to ensure reactors report the correct // behaviour in manufactured scenarios. type MockReporter struct { - mtx sync.RWMutex + mtx tmsync.RWMutex pb map[p2p.ID][]PeerBehaviour } diff --git a/blockchain/v0/pool.go b/blockchain/v0/pool.go index bd8165752..327907bba 100644 --- a/blockchain/v0/pool.go +++ b/blockchain/v0/pool.go @@ -4,14 +4,13 @@ import ( "errors" "fmt" "math" - "sync" "sync/atomic" "time" flow "github.com/tendermint/tendermint/libs/flowrate" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/service" - + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/types" ) @@ -64,7 +63,7 @@ type BlockPool struct { service.BaseService startTime time.Time - mtx sync.Mutex + mtx tmsync.Mutex // block requests requesters map[int64]*bpRequester height int64 // the lowest key in requesters. @@ -510,7 +509,7 @@ type bpRequester struct { gotBlockCh chan struct{} redoCh chan p2p.ID //redo may send multitime, add peerId to identify repeat - mtx sync.Mutex + mtx tmsync.Mutex peerID p2p.ID block *types.Block } diff --git a/blockchain/v2/reactor.go b/blockchain/v2/reactor.go index f5da4e5ff..60cc9517e 100644 --- a/blockchain/v2/reactor.go +++ b/blockchain/v2/reactor.go @@ -3,12 +3,12 @@ package v2 import ( "errors" "fmt" - "sync" "time" "github.com/tendermint/tendermint/behaviour" bc "github.com/tendermint/tendermint/blockchain" "github.com/tendermint/tendermint/libs/log" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" bcproto "github.com/tendermint/tendermint/proto/tendermint/blockchain" "github.com/tendermint/tendermint/state" @@ -37,7 +37,7 @@ type BlockchainReactor struct { processor *Routine logger log.Logger - mtx sync.RWMutex + mtx tmsync.RWMutex maxPeerHeight int64 syncHeight int64 events chan Event // non-nil during a fast sync diff --git a/consensus/common_test.go b/consensus/common_test.go index 1bc93e9d6..cbb11f71c 100644 --- a/consensus/common_test.go +++ b/consensus/common_test.go @@ -30,6 +30,7 @@ import ( "github.com/tendermint/tendermint/libs/log" tmos "github.com/tendermint/tendermint/libs/os" tmpubsub "github.com/tendermint/tendermint/libs/pubsub" + tmsync "github.com/tendermint/tendermint/libs/sync" mempl "github.com/tendermint/tendermint/mempool" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/privval" @@ -375,7 +376,7 @@ func newStateWithConfigAndBlockStore( blockStore := store.NewBlockStore(blockDB) // one for mempool, one for consensus - mtx := new(sync.Mutex) + mtx := new(tmsync.Mutex) proxyAppConnMem := abcicli.NewLocalClient(mtx, app) proxyAppConnCon := abcicli.NewLocalClient(mtx, app) @@ -440,7 +441,7 @@ func randStateWithEvpool(nValidators int) (*State, []*validatorStub, *evidence.P blockStore := store.NewBlockStore(dbm.NewMemDB()) evidenceDB := dbm.NewMemDB() - mtx := new(sync.Mutex) + mtx := new(tmsync.Mutex) proxyAppConnMem := abcicli.NewLocalClient(mtx, app) proxyAppConnCon := abcicli.NewLocalClient(mtx, app) diff --git a/consensus/reactor.go b/consensus/reactor.go index 2de9fcc39..502487eba 100644 --- a/consensus/reactor.go +++ b/consensus/reactor.go @@ -14,6 +14,7 @@ import ( tmevents "github.com/tendermint/tendermint/libs/events" tmjson "github.com/tendermint/tendermint/libs/json" "github.com/tendermint/tendermint/libs/log" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" tmcons "github.com/tendermint/tendermint/proto/tendermint/consensus" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" @@ -42,7 +43,7 @@ type Reactor struct { conS *State - mtx sync.RWMutex + mtx tmsync.RWMutex waitSync bool eventBus *types.EventBus diff --git a/consensus/reactor_test.go b/consensus/reactor_test.go index 054bb9fed..32721eaa9 100644 --- a/consensus/reactor_test.go +++ b/consensus/reactor_test.go @@ -26,6 +26,7 @@ import ( "github.com/tendermint/tendermint/libs/bits" "github.com/tendermint/tendermint/libs/bytes" "github.com/tendermint/tendermint/libs/log" + tmsync "github.com/tendermint/tendermint/libs/sync" mempl "github.com/tendermint/tendermint/mempool" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/p2p/mock" @@ -140,7 +141,7 @@ func TestReactorWithEvidence(t *testing.T) { blockStore := store.NewBlockStore(blockDB) // one for mempool, one for consensus - mtx := new(sync.Mutex) + mtx := new(tmsync.Mutex) proxyAppConnMem := abcicli.NewLocalClient(mtx, app) proxyAppConnCon := abcicli.NewLocalClient(mtx, app) diff --git a/consensus/state.go b/consensus/state.go index 1445dd479..70ccb75bc 100644 --- a/consensus/state.go +++ b/consensus/state.go @@ -8,7 +8,6 @@ import ( "os" "reflect" "runtime/debug" - "sync" "time" "github.com/gogo/protobuf/proto" @@ -22,6 +21,7 @@ import ( tmmath "github.com/tendermint/tendermint/libs/math" tmos "github.com/tendermint/tendermint/libs/os" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" sm "github.com/tendermint/tendermint/state" @@ -98,7 +98,7 @@ type State struct { evpool evidencePool // internal state - mtx sync.RWMutex + mtx tmsync.RWMutex cstypes.RoundState state sm.State // State until height-1. diff --git a/go.mod b/go.mod index b64870349..8bb7573d5 100644 --- a/go.mod +++ b/go.mod @@ -17,10 +17,12 @@ require ( github.com/libp2p/go-buffer-pool v0.0.2 github.com/magiconair/properties v1.8.1 github.com/minio/highwayhash v1.0.0 + github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect github.com/pkg/errors v0.9.1 github.com/prometheus/client_golang v1.7.1 github.com/rcrowley/go-metrics v0.0.0-20200313005456-10cdbea86bc0 github.com/rs/cors v1.7.0 + github.com/sasha-s/go-deadlock v0.2.0 github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa github.com/spf13/cobra v1.0.0 github.com/spf13/viper v1.7.0 diff --git a/go.sum b/go.sum index c6839a832..681c1e47b 100644 --- a/go.sum +++ b/go.sum @@ -337,6 +337,8 @@ github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtP github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 h1:q2e307iGHPdTGp0hoxKjt1H5pDo6utceo3dQVK3I5XQ= +github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5/go.mod h1:jvVRKCrJTQWu0XVbaOlby/2lO20uSCHEMzzplHXte1o= github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -400,6 +402,8 @@ github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/sasha-s/go-deadlock v0.2.0 h1:lMqc+fUb7RrFS3gQLtoQsJ7/6TV/pAIFvBsqX73DK8Y= +github.com/sasha-s/go-deadlock v0.2.0/go.mod h1:StQn567HiB1fF2yJ44N9au7wOhrPS3iZqiDbRupzT10= github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= diff --git a/libs/clist/clist.go b/libs/clist/clist.go index 393bdf73f..5579b1d0f 100644 --- a/libs/clist/clist.go +++ b/libs/clist/clist.go @@ -14,6 +14,8 @@ to ensure garbage collection of removed elements. import ( "fmt" "sync" + + tmsync "github.com/tendermint/tendermint/libs/sync" ) // MaxLength is the max allowed number of elements a linked list is @@ -42,7 +44,7 @@ waiting on NextWait() (since it's just a read operation). */ type CElement struct { - mtx sync.RWMutex + mtx tmsync.RWMutex prev *CElement prevWg *sync.WaitGroup prevWaitCh chan struct{} @@ -218,7 +220,7 @@ func (e *CElement) SetRemoved() { // Operations are goroutine-safe. // Panics if length grows beyond the max. type CList struct { - mtx sync.RWMutex + mtx tmsync.RWMutex wg *sync.WaitGroup waitCh chan struct{} head *CElement // first element diff --git a/libs/cmap/cmap.go b/libs/cmap/cmap.go index da2275d7d..d16631d31 100644 --- a/libs/cmap/cmap.go +++ b/libs/cmap/cmap.go @@ -1,11 +1,13 @@ package cmap -import "sync" +import ( + tmsync "github.com/tendermint/tendermint/libs/sync" +) // CMap is a goroutine-safe map type CMap struct { m map[string]interface{} - l sync.Mutex + l tmsync.Mutex } func NewCMap() *CMap { diff --git a/libs/events/events.go b/libs/events/events.go index 2468e4838..ffc06cc02 100644 --- a/libs/events/events.go +++ b/libs/events/events.go @@ -3,9 +3,9 @@ package events import ( "fmt" - "sync" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" ) // ErrListenerWasRemoved is returned by AddEvent if the listener was removed. @@ -54,7 +54,7 @@ type EventSwitch interface { type eventSwitch struct { service.BaseService - mtx sync.RWMutex + mtx tmsync.RWMutex eventCells map[string]*eventCell listeners map[string]*eventListener } @@ -162,7 +162,7 @@ func (evsw *eventSwitch) FireEvent(event string, data EventData) { // eventCell handles keeping track of listener callbacks for a given event. type eventCell struct { - mtx sync.RWMutex + mtx tmsync.RWMutex listeners map[string]EventCallback } @@ -206,7 +206,7 @@ type EventCallback func(data EventData) type eventListener struct { id string - mtx sync.RWMutex + mtx tmsync.RWMutex removed bool events []string } diff --git a/libs/flowrate/flowrate.go b/libs/flowrate/flowrate.go index 2a053805c..c7ba93282 100644 --- a/libs/flowrate/flowrate.go +++ b/libs/flowrate/flowrate.go @@ -8,13 +8,14 @@ package flowrate import ( "math" - "sync" "time" + + tmsync "github.com/tendermint/tendermint/libs/sync" ) // Monitor monitors and limits the transfer rate of a data stream. type Monitor struct { - mu sync.Mutex // Mutex guarding access to all internal fields + mu tmsync.Mutex // Mutex guarding access to all internal fields active bool // Flag indicating an active transfer start time.Duration // Transfer start time (clock() value) bytes int64 // Total number of bytes transferred diff --git a/libs/json/structs.go b/libs/json/structs.go index b20873c33..2037cdad9 100644 --- a/libs/json/structs.go +++ b/libs/json/structs.go @@ -4,8 +4,9 @@ import ( "fmt" "reflect" "strings" - "sync" "unicode" + + tmsync "github.com/tendermint/tendermint/libs/sync" ) var ( @@ -15,7 +16,7 @@ var ( // structCache is a cache of struct info. type structInfoCache struct { - sync.RWMutex + tmsync.RWMutex structInfos map[reflect.Type]*structInfo } diff --git a/libs/json/types.go b/libs/json/types.go index 9c9493056..13f20d2bc 100644 --- a/libs/json/types.go +++ b/libs/json/types.go @@ -4,7 +4,8 @@ import ( "errors" "fmt" "reflect" - "sync" + + tmsync "github.com/tendermint/tendermint/libs/sync" ) var ( @@ -38,7 +39,7 @@ type typeInfo struct { // types is a type registry. It is safe for concurrent use. type types struct { - sync.RWMutex + tmsync.RWMutex byType map[reflect.Type]*typeInfo byName map[string]*typeInfo } diff --git a/libs/pubsub/pubsub.go b/libs/pubsub/pubsub.go index edf60cf94..f48ee5b86 100644 --- a/libs/pubsub/pubsub.go +++ b/libs/pubsub/pubsub.go @@ -38,9 +38,9 @@ import ( "context" "errors" "fmt" - "sync" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" ) type operation int @@ -96,7 +96,7 @@ type Server struct { // check if we have subscription before // subscribing or unsubscribing - mtx sync.RWMutex + mtx tmsync.RWMutex subscriptions map[string]map[string]struct{} // subscriber -> query (string) -> empty struct } diff --git a/libs/pubsub/subscription.go b/libs/pubsub/subscription.go index cf3923584..4d6f605c7 100644 --- a/libs/pubsub/subscription.go +++ b/libs/pubsub/subscription.go @@ -2,7 +2,8 @@ package pubsub import ( "errors" - "sync" + + tmsync "github.com/tendermint/tendermint/libs/sync" ) var ( @@ -23,7 +24,7 @@ type Subscription struct { out chan Message cancelled chan struct{} - mtx sync.RWMutex + mtx tmsync.RWMutex err error } diff --git a/libs/rand/random.go b/libs/rand/random.go index ddd4432cb..687affd4a 100644 --- a/libs/rand/random.go +++ b/libs/rand/random.go @@ -3,8 +3,9 @@ package rand import ( crand "crypto/rand" mrand "math/rand" - "sync" "time" + + tmsync "github.com/tendermint/tendermint/libs/sync" ) const ( @@ -19,7 +20,7 @@ const ( // All of the methods here are suitable for concurrent use. // This is achieved by using a mutex lock on all of the provided methods. type Rand struct { - sync.Mutex + tmsync.Mutex rand *mrand.Rand } diff --git a/libs/sync/deadlock.go b/libs/sync/deadlock.go new file mode 100644 index 000000000..637d6fbb1 --- /dev/null +++ b/libs/sync/deadlock.go @@ -0,0 +1,17 @@ +// +build deadlock + +package sync + +import ( + deadlock "github.com/sasha-s/go-deadlock" +) + +// A Mutex is a mutual exclusion lock. +type Mutex struct { + deadlock.Mutex +} + +// An RWMutex is a reader/writer mutual exclusion lock. +type RWMutex struct { + deadlock.RWMutex +} diff --git a/libs/sync/sync.go b/libs/sync/sync.go new file mode 100644 index 000000000..a0880e7de --- /dev/null +++ b/libs/sync/sync.go @@ -0,0 +1,15 @@ +// +build !deadlock + +package sync + +import "sync" + +// A Mutex is a mutual exclusion lock. +type Mutex struct { + sync.Mutex +} + +// An RWMutex is a reader/writer mutual exclusion lock. +type RWMutex struct { + sync.RWMutex +} diff --git a/libs/tempfile/tempfile.go b/libs/tempfile/tempfile.go index e30d5a8c6..922ed5722 100644 --- a/libs/tempfile/tempfile.go +++ b/libs/tempfile/tempfile.go @@ -7,8 +7,9 @@ import ( "path/filepath" "strconv" "strings" - "sync" "time" + + tmsync "github.com/tendermint/tendermint/libs/sync" ) const ( @@ -31,7 +32,7 @@ const ( var ( atomicWriteFileRand uint64 - atomicWriteFileRandMu sync.Mutex + atomicWriteFileRandMu tmsync.Mutex ) func writeFileRandReseed() uint64 { diff --git a/libs/timer/throttle_timer.go b/libs/timer/throttle_timer.go index 76db87ee8..7f5660c05 100644 --- a/libs/timer/throttle_timer.go +++ b/libs/timer/throttle_timer.go @@ -1,8 +1,9 @@ package timer import ( - "sync" "time" + + tmsync "github.com/tendermint/tendermint/libs/sync" ) /* @@ -17,7 +18,7 @@ type ThrottleTimer struct { quit chan struct{} dur time.Duration - mtx sync.Mutex + mtx tmsync.Mutex timer *time.Timer isSet bool } diff --git a/libs/timer/throttle_timer_test.go b/libs/timer/throttle_timer_test.go index 894447974..9c2d92b23 100644 --- a/libs/timer/throttle_timer_test.go +++ b/libs/timer/throttle_timer_test.go @@ -1,18 +1,19 @@ package timer import ( - "sync" "testing" "time" // make govet noshadow happy... asrt "github.com/stretchr/testify/assert" + + tmsync "github.com/tendermint/tendermint/libs/sync" ) type thCounter struct { input chan struct{} - mtx sync.Mutex + mtx tmsync.Mutex count int } diff --git a/light/client.go b/light/client.go index 5c5b206ce..319eb582a 100644 --- a/light/client.go +++ b/light/client.go @@ -5,11 +5,11 @@ import ( "errors" "fmt" "math/rand" - "sync" "time" "github.com/tendermint/tendermint/libs/log" tmmath "github.com/tendermint/tendermint/libs/math" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/light/provider" "github.com/tendermint/tendermint/light/store" "github.com/tendermint/tendermint/types" @@ -121,7 +121,7 @@ type Client struct { maxClockDrift time.Duration // Mutex for locking during changes of the light clients providers - providerMutex sync.Mutex + providerMutex tmsync.Mutex // Primary provider of new headers. primary provider.Provider // See Witnesses option diff --git a/light/store/db/db.go b/light/store/db/db.go index f6712eba1..390b02991 100644 --- a/light/store/db/db.go +++ b/light/store/db/db.go @@ -5,11 +5,11 @@ import ( "fmt" "regexp" "strconv" - "sync" "github.com/gogo/protobuf/proto" dbm "github.com/tendermint/tm-db" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/light/store" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" @@ -23,7 +23,7 @@ type dbs struct { db dbm.DB prefix string - mtx sync.RWMutex + mtx tmsync.RWMutex size uint16 } diff --git a/mempool/clist_mempool.go b/mempool/clist_mempool.go index c4b63f8bb..75eabd0a5 100644 --- a/mempool/clist_mempool.go +++ b/mempool/clist_mempool.go @@ -15,6 +15,7 @@ import ( "github.com/tendermint/tendermint/libs/log" tmmath "github.com/tendermint/tendermint/libs/math" tmos "github.com/tendermint/tendermint/libs/os" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" "github.com/tendermint/tendermint/proxy" "github.com/tendermint/tendermint/types" @@ -43,7 +44,7 @@ type CListMempool struct { // Exclusive mutex for Update method to prevent concurrent execution of // CheckTx or ReapMaxBytesMaxGas(ReapMaxTxs) methods. - updateMtx sync.RWMutex + updateMtx tmsync.RWMutex preCheck PreCheckFunc postCheck PostCheckFunc @@ -681,7 +682,7 @@ type txCache interface { // mapTxCache maintains a LRU cache of transactions. This only stores the hash // of the tx, due to memory concerns. type mapTxCache struct { - mtx sync.Mutex + mtx tmsync.Mutex size int cacheMap map[[TxKeySize]byte]*list.Element list *list.List diff --git a/mempool/reactor.go b/mempool/reactor.go index e8fc97474..6e30e4627 100644 --- a/mempool/reactor.go +++ b/mempool/reactor.go @@ -3,12 +3,12 @@ package mempool import ( "fmt" "math" - "sync" "time" cfg "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/libs/clist" "github.com/tendermint/tendermint/libs/log" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" protomem "github.com/tendermint/tendermint/proto/tendermint/mempool" "github.com/tendermint/tendermint/types" @@ -39,7 +39,7 @@ type Reactor struct { } type mempoolIDs struct { - mtx sync.RWMutex + mtx tmsync.RWMutex peerMap map[p2p.ID]uint16 nextID uint16 // assumes that a node will never have over 65536 active peers activeIDs map[uint16]struct{} // used to check if a given peerID key is used, the value doesn't matter diff --git a/p2p/conn/connection.go b/p2p/conn/connection.go index 4920ac0f2..3d5da2e63 100644 --- a/p2p/conn/connection.go +++ b/p2p/conn/connection.go @@ -9,7 +9,6 @@ import ( "net" "reflect" "runtime/debug" - "sync" "sync/atomic" "time" @@ -20,6 +19,7 @@ import ( tmmath "github.com/tendermint/tendermint/libs/math" "github.com/tendermint/tendermint/libs/protoio" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/libs/timer" tmp2p "github.com/tendermint/tendermint/proto/tendermint/p2p" ) @@ -101,7 +101,7 @@ type MConnection struct { // used to ensure FlushStop and OnStop // are safe to call concurrently. - stopMtx sync.Mutex + stopMtx tmsync.Mutex flushTimer *timer.ThrottleTimer // flush writes as necessary but throttled. pingTimer *time.Ticker // send pings periodically diff --git a/p2p/conn/secret_connection.go b/p2p/conn/secret_connection.go index 5e0f2d2cc..d53cf0635 100644 --- a/p2p/conn/secret_connection.go +++ b/p2p/conn/secret_connection.go @@ -11,7 +11,6 @@ import ( "io" "math" "net" - "sync" "time" gogotypes "github.com/gogo/protobuf/types" @@ -27,6 +26,7 @@ import ( cryptoenc "github.com/tendermint/tendermint/crypto/encoding" "github.com/tendermint/tendermint/libs/async" "github.com/tendermint/tendermint/libs/protoio" + tmsync "github.com/tendermint/tendermint/libs/sync" tmp2p "github.com/tendermint/tendermint/proto/tendermint/p2p" ) @@ -76,11 +76,11 @@ type SecretConnection struct { // are independent, so we can use two mtxs. // All .Read are covered by recvMtx, // all .Write are covered by sendMtx. - recvMtx sync.Mutex + recvMtx tmsync.Mutex recvBuffer []byte recvNonce *[aeadNonceSize]byte - sendMtx sync.Mutex + sendMtx tmsync.Mutex sendNonce *[aeadNonceSize]byte } diff --git a/p2p/conn_set.go b/p2p/conn_set.go index a889ad5e1..376510d72 100644 --- a/p2p/conn_set.go +++ b/p2p/conn_set.go @@ -2,7 +2,8 @@ package p2p import ( "net" - "sync" + + tmsync "github.com/tendermint/tendermint/libs/sync" ) // ConnSet is a lookup table for connections and all their ips. @@ -20,7 +21,7 @@ type connSetItem struct { } type connSet struct { - sync.RWMutex + tmsync.RWMutex conns map[string]connSetItem } diff --git a/p2p/fuzz.go b/p2p/fuzz.go index ce9dfb394..0ada85ecc 100644 --- a/p2p/fuzz.go +++ b/p2p/fuzz.go @@ -2,11 +2,11 @@ package p2p import ( "net" - "sync" "time" "github.com/tendermint/tendermint/config" tmrand "github.com/tendermint/tendermint/libs/rand" + tmsync "github.com/tendermint/tendermint/libs/sync" ) // FuzzedConnection wraps any net.Conn and depending on the mode either delays @@ -14,7 +14,7 @@ import ( type FuzzedConnection struct { conn net.Conn - mtx sync.Mutex + mtx tmsync.Mutex start <-chan time.Time active bool diff --git a/p2p/peer_set.go b/p2p/peer_set.go index 87cf61da0..38dff7a9f 100644 --- a/p2p/peer_set.go +++ b/p2p/peer_set.go @@ -2,7 +2,8 @@ package p2p import ( "net" - "sync" + + tmsync "github.com/tendermint/tendermint/libs/sync" ) // IPeerSet has a (immutable) subset of the methods of PeerSet. @@ -19,7 +20,7 @@ type IPeerSet interface { // PeerSet is a special structure for keeping a table of peers. // Iteration over the peers is super fast and thread-safe. type PeerSet struct { - mtx sync.Mutex + mtx tmsync.Mutex lookup map[ID]*peerSetItem list []Peer } diff --git a/p2p/pex/addrbook.go b/p2p/pex/addrbook.go index c47177984..5bb934056 100644 --- a/p2p/pex/addrbook.go +++ b/p2p/pex/addrbook.go @@ -20,6 +20,7 @@ import ( tmmath "github.com/tendermint/tendermint/libs/math" tmrand "github.com/tendermint/tendermint/libs/rand" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" ) @@ -87,7 +88,7 @@ type addrBook struct { service.BaseService // accessed concurrently - mtx sync.Mutex + mtx tmsync.Mutex rand *tmrand.Rand ourAddrs map[string]struct{} privateIDs map[p2p.ID]struct{} diff --git a/p2p/switch_test.go b/p2p/switch_test.go index e5529161b..82cb6b06d 100644 --- a/p2p/switch_test.go +++ b/p2p/switch_test.go @@ -11,7 +11,6 @@ import ( "net/http/httptest" "regexp" "strconv" - "sync" "sync/atomic" "testing" "time" @@ -23,6 +22,7 @@ import ( "github.com/tendermint/tendermint/config" "github.com/tendermint/tendermint/crypto/ed25519" "github.com/tendermint/tendermint/libs/log" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p/conn" ) @@ -45,7 +45,7 @@ type PeerMessage struct { type TestReactor struct { BaseReactor - mtx sync.Mutex + mtx tmsync.Mutex channels []*conn.ChannelDescriptor logMessages bool msgsCounter int diff --git a/p2p/trust/metric.go b/p2p/trust/metric.go index b54415ed8..dd2d75d43 100644 --- a/p2p/trust/metric.go +++ b/p2p/trust/metric.go @@ -5,10 +5,10 @@ package trust import ( "math" - "sync" "time" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" ) //--------------------------------------------------------------------------------------- @@ -36,7 +36,7 @@ type Metric struct { service.BaseService // Mutex that protects the metric from concurrent access - mtx sync.Mutex + mtx tmsync.Mutex // Determines the percentage given to current behavior proportionalWeight float64 diff --git a/p2p/trust/store.go b/p2p/trust/store.go index 166b26b1c..6fa2c4f44 100644 --- a/p2p/trust/store.go +++ b/p2p/trust/store.go @@ -6,12 +6,12 @@ package trust import ( "encoding/json" "fmt" - "sync" "time" dbm "github.com/tendermint/tm-db" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" ) const defaultStorePeriodicSaveInterval = 1 * time.Minute @@ -26,7 +26,7 @@ type MetricStore struct { peerMetrics map[string]*Metric // Mutex that protects the map and history data file - mtx sync.Mutex + mtx tmsync.Mutex // The db where peer trust metric history data will be stored db dbm.DB diff --git a/privval/signer_endpoint.go b/privval/signer_endpoint.go index aabb0b2da..8ea5e2f8a 100644 --- a/privval/signer_endpoint.go +++ b/privval/signer_endpoint.go @@ -3,11 +3,11 @@ package privval import ( "fmt" "net" - "sync" "time" "github.com/tendermint/tendermint/libs/protoio" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" privvalproto "github.com/tendermint/tendermint/proto/tendermint/privval" ) @@ -18,7 +18,7 @@ const ( type signerEndpoint struct { service.BaseService - connMtx sync.Mutex + connMtx tmsync.Mutex conn net.Conn timeoutReadWrite time.Duration diff --git a/privval/signer_listener_endpoint.go b/privval/signer_listener_endpoint.go index 2c7609afd..1f05995fa 100644 --- a/privval/signer_listener_endpoint.go +++ b/privval/signer_listener_endpoint.go @@ -3,11 +3,11 @@ package privval import ( "fmt" "net" - "sync" "time" "github.com/tendermint/tendermint/libs/log" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" privvalproto "github.com/tendermint/tendermint/proto/tendermint/privval" ) @@ -26,7 +26,7 @@ type SignerListenerEndpoint struct { timeoutAccept time.Duration pingTimer *time.Ticker - instanceMtx sync.Mutex // Ensures instance public methods access, i.e. SendRequest + instanceMtx tmsync.Mutex // Ensures instance public methods access, i.e. SendRequest } // NewSignerListenerEndpoint returns an instance of SignerListenerEndpoint. diff --git a/privval/signer_server.go b/privval/signer_server.go index a8c28e541..c14524e36 100644 --- a/privval/signer_server.go +++ b/privval/signer_server.go @@ -2,9 +2,9 @@ package privval import ( "io" - "sync" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" privvalproto "github.com/tendermint/tendermint/proto/tendermint/privval" "github.com/tendermint/tendermint/types" ) @@ -22,7 +22,7 @@ type SignerServer struct { chainID string privVal types.PrivValidator - handlerMtx sync.Mutex + handlerMtx tmsync.Mutex validationRequestHandler ValidationRequestHandlerFunc } diff --git a/proxy/client.go b/proxy/client.go index f92b258e6..0586dd21d 100644 --- a/proxy/client.go +++ b/proxy/client.go @@ -2,12 +2,12 @@ package proxy import ( "fmt" - "sync" abcicli "github.com/tendermint/tendermint/abci/client" "github.com/tendermint/tendermint/abci/example/counter" "github.com/tendermint/tendermint/abci/example/kvstore" "github.com/tendermint/tendermint/abci/types" + tmsync "github.com/tendermint/tendermint/libs/sync" ) // ClientCreator creates new ABCI clients. @@ -20,7 +20,7 @@ type ClientCreator interface { // local proxy uses a mutex on an in-proc app type localClientCreator struct { - mtx *sync.Mutex + mtx *tmsync.Mutex app types.Application } @@ -28,7 +28,7 @@ type localClientCreator struct { // which will be running locally. func NewLocalClientCreator(app types.Application) ClientCreator { return &localClientCreator{ - mtx: new(sync.Mutex), + mtx: new(tmsync.Mutex), app: app, } } diff --git a/rpc/client/http/http.go b/rpc/client/http/http.go index e253080fc..25e0fe5ee 100644 --- a/rpc/client/http/http.go +++ b/rpc/client/http/http.go @@ -5,7 +5,6 @@ import ( "errors" "net/http" "strings" - "sync" "time" "github.com/tendermint/tendermint/libs/bytes" @@ -13,6 +12,7 @@ import ( "github.com/tendermint/tendermint/libs/log" tmpubsub "github.com/tendermint/tendermint/libs/pubsub" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" rpcclient "github.com/tendermint/tendermint/rpc/client" ctypes "github.com/tendermint/tendermint/rpc/core/types" jsonrpcclient "github.com/tendermint/tendermint/rpc/jsonrpc/client" @@ -491,7 +491,7 @@ type WSEvents struct { endpoint string ws *jsonrpcclient.WSClient - mtx sync.RWMutex + mtx tmsync.RWMutex subscriptions map[string]chan ctypes.ResultEvent // query -> chan } diff --git a/rpc/jsonrpc/client/http_json_client.go b/rpc/jsonrpc/client/http_json_client.go index 78c884734..0a38332a1 100644 --- a/rpc/jsonrpc/client/http_json_client.go +++ b/rpc/jsonrpc/client/http_json_client.go @@ -9,8 +9,8 @@ import ( "net/http" "net/url" "strings" - "sync" + tmsync "github.com/tendermint/tendermint/libs/sync" types "github.com/tendermint/tendermint/rpc/jsonrpc/types" ) @@ -99,7 +99,7 @@ type Client struct { client *http.Client - mtx sync.Mutex + mtx tmsync.Mutex nextReqID int } @@ -260,7 +260,7 @@ type jsonRPCBufferedRequest struct { type RequestBatch struct { client *Client - mtx sync.Mutex + mtx tmsync.Mutex requests []*jsonRPCBufferedRequest } diff --git a/rpc/jsonrpc/client/ws_client.go b/rpc/jsonrpc/client/ws_client.go index 9f0d36c1f..030b69173 100644 --- a/rpc/jsonrpc/client/ws_client.go +++ b/rpc/jsonrpc/client/ws_client.go @@ -14,6 +14,7 @@ import ( tmrand "github.com/tendermint/tendermint/libs/rand" "github.com/tendermint/tendermint/libs/service" + tmsync "github.com/tendermint/tendermint/libs/sync" types "github.com/tendermint/tendermint/rpc/jsonrpc/types" ) @@ -56,7 +57,7 @@ type WSClient struct { // nolint: maligned wg sync.WaitGroup - mtx sync.RWMutex + mtx tmsync.RWMutex sentLastPingAt time.Time reconnecting bool nextReqID int diff --git a/rpc/jsonrpc/client/ws_client_test.go b/rpc/jsonrpc/client/ws_client_test.go index 25960a5bc..2e6403806 100644 --- a/rpc/jsonrpc/client/ws_client_test.go +++ b/rpc/jsonrpc/client/ws_client_test.go @@ -13,7 +13,7 @@ import ( "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/libs/log" - + tmsync "github.com/tendermint/tendermint/libs/sync" types "github.com/tendermint/tendermint/rpc/jsonrpc/types" ) @@ -21,7 +21,7 @@ var wsCallTimeout = 5 * time.Second type myHandler struct { closeConnAfterRead bool - mtx sync.RWMutex + mtx tmsync.RWMutex } var upgrader = websocket.Upgrader{ diff --git a/statesync/chunks.go b/statesync/chunks.go index 0ce076baf..028c863b9 100644 --- a/statesync/chunks.go +++ b/statesync/chunks.go @@ -7,9 +7,9 @@ import ( "os" "path/filepath" "strconv" - "sync" "time" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" ) @@ -29,7 +29,7 @@ type chunk struct { // iterator over all chunks, but callers can request chunks to be retried, optionally after // refetching. type chunkQueue struct { - sync.Mutex + tmsync.Mutex snapshot *snapshot // if this is nil, the queue has been closed dir string // temp dir for on-disk chunk storage chunkFiles map[uint32]string // path to temporary chunk file diff --git a/statesync/reactor.go b/statesync/reactor.go index 82c435fbb..dec60c2c9 100644 --- a/statesync/reactor.go +++ b/statesync/reactor.go @@ -3,9 +3,9 @@ package statesync import ( "errors" "sort" - "sync" abci "github.com/tendermint/tendermint/abci/types" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync" "github.com/tendermint/tendermint/proxy" @@ -33,7 +33,7 @@ type Reactor struct { // This will only be set when a state sync is in progress. It is used to feed received // snapshots and chunks into the sync. - mtx sync.RWMutex + mtx tmsync.RWMutex syncer *syncer } diff --git a/statesync/snapshots.go b/statesync/snapshots.go index a2afb4083..c9ee4cd46 100644 --- a/statesync/snapshots.go +++ b/statesync/snapshots.go @@ -5,8 +5,8 @@ import ( "fmt" "math/rand" "sort" - "sync" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" ) @@ -42,7 +42,7 @@ func (s *snapshot) Key() snapshotKey { type snapshotPool struct { stateProvider StateProvider - sync.Mutex + tmsync.Mutex snapshots map[snapshotKey]*snapshot snapshotPeers map[snapshotKey]map[p2p.ID]p2p.Peer diff --git a/statesync/stateprovider.go b/statesync/stateprovider.go index dfc8c15c5..f07fd077e 100644 --- a/statesync/stateprovider.go +++ b/statesync/stateprovider.go @@ -3,12 +3,12 @@ package statesync import ( "fmt" "strings" - "sync" "time" dbm "github.com/tendermint/tm-db" "github.com/tendermint/tendermint/libs/log" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/light" lightprovider "github.com/tendermint/tendermint/light/provider" lighthttp "github.com/tendermint/tendermint/light/provider/http" @@ -35,10 +35,10 @@ type StateProvider interface { // lightClientStateProvider is a state provider using the light client. type lightClientStateProvider struct { - sync.Mutex // light.Client is not concurrency-safe - lc *light.Client - version tmstate.Version - providers map[lightprovider.Provider]string + tmsync.Mutex // light.Client is not concurrency-safe + lc *light.Client + version tmstate.Version + providers map[lightprovider.Provider]string } // NewLightClientStateProvider creates a new StateProvider using a light client and RPC clients. diff --git a/statesync/syncer.go b/statesync/syncer.go index a805851c9..45bd0fe63 100644 --- a/statesync/syncer.go +++ b/statesync/syncer.go @@ -5,11 +5,11 @@ import ( "context" "errors" "fmt" - "sync" "time" abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" ssproto "github.com/tendermint/tendermint/proto/tendermint/statesync" "github.com/tendermint/tendermint/proxy" @@ -58,7 +58,7 @@ type syncer struct { snapshots *snapshotPool tempDir string - mtx sync.RWMutex + mtx tmsync.RWMutex chunks *chunkQueue } diff --git a/statesync/syncer_test.go b/statesync/syncer_test.go index 793f9ef6c..d0bf2aaf5 100644 --- a/statesync/syncer_test.go +++ b/statesync/syncer_test.go @@ -2,7 +2,6 @@ package statesync import ( "errors" - "sync" "testing" "time" @@ -12,6 +11,7 @@ import ( abci "github.com/tendermint/tendermint/abci/types" "github.com/tendermint/tendermint/libs/log" + tmsync "github.com/tendermint/tendermint/libs/sync" "github.com/tendermint/tendermint/p2p" p2pmocks "github.com/tendermint/tendermint/p2p/mocks" tmstate "github.com/tendermint/tendermint/proto/tendermint/state" @@ -140,7 +140,7 @@ func TestSyncer_SyncAny(t *testing.T) { }).Times(2).Return(&abci.ResponseOfferSnapshot{Result: abci.ResponseOfferSnapshot_ACCEPT}, nil) chunkRequests := make(map[uint32]int) - chunkRequestsMtx := sync.Mutex{} + chunkRequestsMtx := tmsync.Mutex{} onChunkRequest := func(args mock.Arguments) { pb, err := decodeMsg(args[1].([]byte)) require.NoError(t, err) diff --git a/store/store.go b/store/store.go index b81bae844..846e1fe7c 100644 --- a/store/store.go +++ b/store/store.go @@ -3,11 +3,11 @@ package store import ( "fmt" "strconv" - "sync" "github.com/gogo/protobuf/proto" dbm "github.com/tendermint/tm-db" + tmsync "github.com/tendermint/tendermint/libs/sync" tmstore "github.com/tendermint/tendermint/proto/tendermint/store" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" "github.com/tendermint/tendermint/types" @@ -33,7 +33,7 @@ The store can be assumed to contain all contiguous blocks between base and heigh type BlockStore struct { db dbm.DB - mtx sync.RWMutex + mtx tmsync.RWMutex base int64 height int64 } diff --git a/tests.mk b/tests.mk index d7e305312..56386d6c8 100644 --- a/tests.mk +++ b/tests.mk @@ -103,7 +103,7 @@ vagrant_test: ### go tests test: @echo "--> Running go test" - @go test -p 1 $(PACKAGES) + @go test -p 1 $(PACKAGES) -tags deadlock .PHONY: test test_race: @@ -111,28 +111,7 @@ test_race: @go test -p 1 -v -race $(PACKAGES) .PHONY: test_race -# uses https://github.com/sasha-s/go-deadlock/ to detect potential deadlocks -test_with_deadlock: - make set_with_deadlock - make test - make cleanup_after_test_with_deadlock -.PHONY: test_with_deadlock - -set_with_deadlock: - @echo "Get Goid" - @go get github.com/petermattis/goid@b0b1615b78e5ee59739545bb38426383b2cda4c9 - @echo "Get Go-Deadlock" - @go get github.com/sasha-s/go-deadlock@d68e2bc52ae3291765881b9056f2c1527f245f1e - find . -name "*.go" | grep -v "vendor/" | xargs -n 1 sed -i.bak 's/sync.RWMutex/deadlock.RWMutex/' - find . -name "*.go" | grep -v "vendor/" | xargs -n 1 sed -i.bak 's/sync.Mutex/deadlock.Mutex/' - find . -name "*.go" | grep -v "vendor/" | xargs -n 1 goimports -w -.PHONY: set_with_deadlock - -# cleanes up after you ran test_with_deadlock -cleanup_after_test_with_deadlock: - find . -name "*.go" | grep -v "vendor/" | xargs -n 1 sed -i.bak 's/deadlock.RWMutex/sync.RWMutex/' - find . -name "*.go" | grep -v "vendor/" | xargs -n 1 sed -i.bak 's/deadlock.Mutex/sync.Mutex/' - find . -name "*.go" | grep -v "vendor/" | xargs -n 1 goimports -w - # cleans up the deps to not include the need libs - go mod tidy -.PHONY: cleanup_after_test_with_deadlock +test_deadlock: + @echo "--> Running go test --deadlock" + @go test -p 1 -v $(PACKAGES) -tags deadlock +.PHONY: test_race diff --git a/types/block.go b/types/block.go index 47e3c9906..c5d62df9f 100644 --- a/types/block.go +++ b/types/block.go @@ -5,7 +5,6 @@ import ( "errors" "fmt" "strings" - "sync" "time" "github.com/gogo/protobuf/proto" @@ -17,6 +16,7 @@ import ( "github.com/tendermint/tendermint/libs/bits" tmbytes "github.com/tendermint/tendermint/libs/bytes" tmmath "github.com/tendermint/tendermint/libs/math" + tmsync "github.com/tendermint/tendermint/libs/sync" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" tmversion "github.com/tendermint/tendermint/proto/tendermint/version" ) @@ -38,7 +38,7 @@ const ( // Block defines the atomic unit of a Tendermint blockchain. type Block struct { - mtx sync.Mutex + mtx tmsync.Mutex Header `json:"header"` Data `json:"data"` diff --git a/types/part_set.go b/types/part_set.go index 472391204..5f730aa3e 100644 --- a/types/part_set.go +++ b/types/part_set.go @@ -5,13 +5,13 @@ import ( "errors" "fmt" "io" - "sync" "github.com/tendermint/tendermint/crypto/merkle" "github.com/tendermint/tendermint/libs/bits" tmbytes "github.com/tendermint/tendermint/libs/bytes" tmjson "github.com/tendermint/tendermint/libs/json" tmmath "github.com/tendermint/tendermint/libs/math" + tmsync "github.com/tendermint/tendermint/libs/sync" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) @@ -141,7 +141,7 @@ type PartSet struct { total uint32 hash []byte - mtx sync.Mutex + mtx tmsync.Mutex parts []*Part partsBitArray *bits.BitArray count uint32 diff --git a/types/vote_set.go b/types/vote_set.go index c61a3d698..6c2b08f67 100644 --- a/types/vote_set.go +++ b/types/vote_set.go @@ -4,10 +4,10 @@ import ( "bytes" "fmt" "strings" - "sync" "github.com/tendermint/tendermint/libs/bits" tmjson "github.com/tendermint/tendermint/libs/json" + tmsync "github.com/tendermint/tendermint/libs/sync" tmproto "github.com/tendermint/tendermint/proto/tendermint/types" ) @@ -65,7 +65,7 @@ type VoteSet struct { signedMsgType tmproto.SignedMsgType valSet *ValidatorSet - mtx sync.Mutex + mtx tmsync.Mutex votesBitArray *bits.BitArray votes []*Vote // Primary votes to share sum int64 // Sum of voting power for seen votes, discounting conflicts