Browse Source

fix race conditions

pull/9/head
Jae Kwon 10 years ago
parent
commit
946fa21dc7
3 changed files with 26 additions and 12 deletions
  1. +3
    -0
      Makefile
  2. +19
    -12
      binary/reflect.go
  3. +4
    -0
      consensus/reactor.go

+ 3
- 0
Makefile View File

@ -3,6 +3,9 @@ all: build
build: build:
go build -o tendermint github.com/tendermint/tendermint/cmd go build -o tendermint github.com/tendermint/tendermint/cmd
build_race:
go build -race -o tendermint github.com/tendermint/tendermint/cmd
test: test:
go test github.com/tendermint/tendermint/... go test github.com/tendermint/tendermint/...


+ 19
- 12
binary/reflect.go View File

@ -5,6 +5,7 @@ import (
"fmt" "fmt"
"io" "io"
"reflect" "reflect"
"sync"
) )
type TypeInfo struct { type TypeInfo struct {
@ -27,8 +28,23 @@ type HasTypeByte interface {
TypeByte() byte TypeByte() byte
} }
// NOTE: do not access typeInfos directly, but call GetTypeInfo()
var typeInfosMtx sync.Mutex
var typeInfos = map[reflect.Type]*TypeInfo{} var typeInfos = map[reflect.Type]*TypeInfo{}
func GetTypeInfo(rt reflect.Type) *TypeInfo {
typeInfosMtx.Lock()
defer typeInfosMtx.Unlock()
info := typeInfos[rt]
if info == nil {
info = &TypeInfo{Type: rt}
RegisterType(info)
}
return info
}
// Registers and possibly modifies the TypeInfo.
// NOTE: not goroutine safe, so only call upon program init.
func RegisterType(info *TypeInfo) *TypeInfo { func RegisterType(info *TypeInfo) *TypeInfo {
// Register the type info // Register the type info
@ -74,10 +90,7 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *
} }
// Get typeInfo // Get typeInfo
typeInfo := typeInfos[rt]
if typeInfo == nil {
typeInfo = RegisterType(&TypeInfo{Type: rt})
}
typeInfo := GetTypeInfo(rt)
// Custom decoder // Custom decoder
if typeInfo.Decoder != nil { if typeInfo.Decoder != nil {
@ -178,10 +191,7 @@ func readReflect(rv reflect.Value, rt reflect.Type, r io.Reader, n *int64, err *
func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err *error) { func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err *error) {
// Get typeInfo // Get typeInfo
typeInfo := typeInfos[rt]
if typeInfo == nil {
typeInfo = RegisterType(&TypeInfo{Type: rt})
}
typeInfo := GetTypeInfo(rt)
// Custom encoder, say for an interface type rt. // Custom encoder, say for an interface type rt.
if typeInfo.Encoder != nil { if typeInfo.Encoder != nil {
@ -193,11 +203,8 @@ func writeReflect(rv reflect.Value, rt reflect.Type, w io.Writer, n *int64, err
if rt.Kind() == reflect.Interface { if rt.Kind() == reflect.Interface {
rv = rv.Elem() rv = rv.Elem()
rt = rv.Type() rt = rv.Type()
typeInfo = typeInfos[rt]
// If interface type, get typeInfo of underlying type. // If interface type, get typeInfo of underlying type.
if typeInfo == nil {
typeInfo = RegisterType(&TypeInfo{Type: rt})
}
typeInfo = GetTypeInfo(rt)
} }
// Dereference pointer // Dereference pointer


+ 4
- 0
consensus/reactor.go View File

@ -323,7 +323,11 @@ OUTER_LOOP:
trySendVote := func(voteSet *VoteSet, peerVoteSet BitArray) (sent bool) { trySendVote := func(voteSet *VoteSet, peerVoteSet BitArray) (sent bool) {
// TODO: give priority to our vote. // TODO: give priority to our vote.
// peerVoteSet BitArray is being accessed concurrently with
// writes from Receive() routines. We must lock like so here:
ps.mtx.Lock()
index, ok := voteSet.BitArray().Sub(peerVoteSet).PickRandom() index, ok := voteSet.BitArray().Sub(peerVoteSet).PickRandom()
ps.mtx.Unlock()
if ok { if ok {
vote := voteSet.GetByIndex(index) vote := voteSet.GetByIndex(index)
// NOTE: vote may be a commit. // NOTE: vote may be a commit.


Loading…
Cancel
Save