eth, xeth: fix GasPriceOracle goroutine leak

XEth.gpo was being initialized as needed. WithState copies the XEth
struct including the gpo field. If gpo was nil at the time of the copy
and Call or Transact were invoked on it, an additional GPO listenLoop
would be spawned.

Move the lazy initialization to GasPriceOracle instead so the same GPO
instance is shared among all created XEths.

Fixes #1317
Might help with #1930
This commit is contained in:
Felix Lange
2015-10-26 21:42:24 +01:00
parent 77878f76a9
commit ae1b5b3ff2
2 changed files with 75 additions and 73 deletions

View File

@ -59,24 +59,8 @@ const (
LogFilterTy
)
func DefaultGas() *big.Int { return new(big.Int).Set(defaultGas) }
func (self *XEth) DefaultGasPrice() *big.Int {
if self.gpo == nil {
self.gpo = eth.NewGasPriceOracle(self.backend)
}
return self.gpo.SuggestPrice()
}
type XEth struct {
backend *eth.Ethereum
frontend Frontend
state *State
whisper *Whisper
quit chan struct{}
filterManager *filters.FilterSystem
quit chan struct{}
logMu sync.RWMutex
logQueue map[int]*logQueue
@ -92,16 +76,18 @@ type XEth struct {
transactMu sync.Mutex
agent *miner.RemoteAgent
gpo *eth.GasPriceOracle
// read-only fields
backend *eth.Ethereum
frontend Frontend
agent *miner.RemoteAgent
gpo *eth.GasPriceOracle
state *State
whisper *Whisper
filterManager *filters.FilterSystem
}
func NewTest(eth *eth.Ethereum, frontend Frontend) *XEth {
return &XEth{
backend: eth,
frontend: frontend,
}
return &XEth{backend: eth, frontend: frontend}
}
// New creates an XEth that uses the given frontend.
@ -118,6 +104,7 @@ func New(ethereum *eth.Ethereum, frontend Frontend) *XEth {
transactionQueue: make(map[int]*hashQueue),
messages: make(map[int]*whisperFilter),
agent: miner.NewRemoteAgent(),
gpo: eth.NewGasPriceOracle(ethereum),
}
if ethereum.Whisper() != nil {
xeth.whisper = NewWhisper(ethereum.Whisper())
@ -207,6 +194,12 @@ func cTopics(t [][]string) [][]common.Hash {
return topics
}
func DefaultGas() *big.Int { return new(big.Int).Set(defaultGas) }
func (self *XEth) DefaultGasPrice() *big.Int {
return self.gpo.SuggestPrice()
}
func (self *XEth) RemoteMining() *miner.RemoteAgent { return self.agent }
func (self *XEth) AtStateNum(num int64) *XEth {