Merge pull request #126 from barakmich/replcrash
Temporarily fix REPL crash by locking the kill channel
This commit is contained in:
commit
720a80a51f
1 changed files with 32 additions and 11 deletions
|
|
@ -94,8 +94,11 @@ func (s *Session) SendResult(r *Result) bool {
|
||||||
if s.limit >= 0 && s.limit == s.count {
|
if s.limit >= 0 && s.limit == s.count {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
s.envLock.Lock()
|
||||||
|
kill := s.kill
|
||||||
|
s.envLock.Unlock()
|
||||||
select {
|
select {
|
||||||
case <-s.kill:
|
case <-kill:
|
||||||
return false
|
return false
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
|
|
@ -112,7 +115,6 @@ func (s *Session) SendResult(r *Result) bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) runUnsafe(input interface{}) (otto.Value, error) {
|
func (s *Session) runUnsafe(input interface{}) (otto.Value, error) {
|
||||||
s.kill = make(chan struct{})
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if r := recover(); r != nil {
|
if r := recover(); r != nil {
|
||||||
if r == ErrKillTimeout {
|
if r == ErrKillTimeout {
|
||||||
|
|
@ -126,25 +128,41 @@ func (s *Session) runUnsafe(input interface{}) (otto.Value, error) {
|
||||||
// Use buffered chan to prevent blocking.
|
// Use buffered chan to prevent blocking.
|
||||||
s.env.Interrupt = make(chan func(), 1)
|
s.env.Interrupt = make(chan func(), 1)
|
||||||
|
|
||||||
|
ready := make(chan struct{})
|
||||||
|
done := make(chan struct{})
|
||||||
if s.timeout >= 0 {
|
if s.timeout >= 0 {
|
||||||
go func() {
|
go func() {
|
||||||
time.Sleep(s.timeout)
|
time.Sleep(s.timeout)
|
||||||
|
<-ready
|
||||||
|
select {
|
||||||
|
case <-done:
|
||||||
|
return
|
||||||
|
default:
|
||||||
close(s.kill)
|
close(s.kill)
|
||||||
s.envLock.Lock()
|
s.envLock.Lock()
|
||||||
defer s.envLock.Unlock()
|
defer s.envLock.Unlock()
|
||||||
|
s.kill = nil
|
||||||
if s.env != nil {
|
if s.env != nil {
|
||||||
s.env.Interrupt <- func() {
|
s.env.Interrupt <- func() {
|
||||||
panic(ErrKillTimeout)
|
panic(ErrKillTimeout)
|
||||||
}
|
}
|
||||||
s.env = s.emptyEnv
|
s.env = s.emptyEnv
|
||||||
}
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
s.envLock.Lock()
|
s.envLock.Lock()
|
||||||
env := s.env
|
env := s.env
|
||||||
|
if s.kill == nil {
|
||||||
|
s.kill = make(chan struct{})
|
||||||
|
}
|
||||||
s.envLock.Unlock()
|
s.envLock.Unlock()
|
||||||
return env.Run(input)
|
close(ready)
|
||||||
|
out, err := env.Run(input)
|
||||||
|
close(done)
|
||||||
|
return out, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Session) ExecInput(input string, out chan interface{}, limit int) {
|
func (s *Session) ExecInput(input string, out chan interface{}, limit int) {
|
||||||
|
|
@ -255,8 +273,11 @@ func (s *Session) GetJson() ([]interface{}, error) {
|
||||||
if s.err != nil {
|
if s.err != nil {
|
||||||
return nil, s.err
|
return nil, s.err
|
||||||
}
|
}
|
||||||
|
s.envLock.Lock()
|
||||||
|
kill := s.kill
|
||||||
|
s.envLock.Unlock()
|
||||||
select {
|
select {
|
||||||
case <-s.kill:
|
case <-kill:
|
||||||
return nil, ErrKillTimeout
|
return nil, ErrKillTimeout
|
||||||
default:
|
default:
|
||||||
return s.dataOutput, nil
|
return s.dataOutput, nil
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue