internal/jsre: ensure Stop can be called more than once

This makes "geth js file.js" terminate again.
This commit is contained in:
Felix Lange 2016-06-02 21:20:32 +02:00
parent 16a23ff740
commit fdba0cb03c
1 changed files with 9 additions and 7 deletions

View File

@ -24,7 +24,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"math/rand" "math/rand"
"sync"
"time" "time"
"github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common"
@ -44,7 +43,7 @@ type JSRE struct {
output io.Writer output io.Writer
evalQueue chan *evalReq evalQueue chan *evalReq
stopEventLoop chan bool stopEventLoop chan bool
loopWg sync.WaitGroup closed chan struct{}
} }
// jsTimer is a single timer instance with a callback function // jsTimer is a single timer instance with a callback function
@ -66,10 +65,10 @@ func New(assetPath string, output io.Writer) *JSRE {
re := &JSRE{ re := &JSRE{
assetPath: assetPath, assetPath: assetPath,
output: output, output: output,
closed: make(chan struct{}),
evalQueue: make(chan *evalReq), evalQueue: make(chan *evalReq),
stopEventLoop: make(chan bool), stopEventLoop: make(chan bool),
} }
re.loopWg.Add(1)
go re.runEventLoop() go re.runEventLoop()
re.Set("loadScript", re.loadScript) re.Set("loadScript", re.loadScript)
re.Set("inspect", prettyPrintJS) re.Set("inspect", prettyPrintJS)
@ -98,6 +97,8 @@ func randomSource() *rand.Rand {
// functions should be used if and only if running a routine that was already // functions should be used if and only if running a routine that was already
// called from JS through an RPC call. // called from JS through an RPC call.
func (self *JSRE) runEventLoop() { func (self *JSRE) runEventLoop() {
defer close(self.closed)
vm := otto.New() vm := otto.New()
r := randomSource() r := randomSource()
vm.SetRandomSource(r.Float64) vm.SetRandomSource(r.Float64)
@ -213,8 +214,6 @@ loop:
timer.timer.Stop() timer.timer.Stop()
delete(registry, timer) delete(registry, timer)
} }
self.loopWg.Done()
} }
// Do executes the given function on the JS event loop. // Do executes the given function on the JS event loop.
@ -227,8 +226,11 @@ func (self *JSRE) Do(fn func(*otto.Otto)) {
// stops the event loop before exit, optionally waits for all timers to expire // stops the event loop before exit, optionally waits for all timers to expire
func (self *JSRE) Stop(waitForCallbacks bool) { func (self *JSRE) Stop(waitForCallbacks bool) {
self.stopEventLoop <- waitForCallbacks select {
self.loopWg.Wait() case <-self.closed:
case self.stopEventLoop <- waitForCallbacks:
<-self.closed
}
} }
// Exec(file) loads and runs the contents of a file // Exec(file) loads and runs the contents of a file