forked from gen0cide/gscript
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathexecutor.go
61 lines (53 loc) · 1.46 KB
/
executor.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
package engine
import (
"errors"
"time"
"github.com/robertkrimen/otto"
"github.com/robertkrimen/otto/ast"
)
var errTimeout = errors.New("Script Timeout")
// SetEntryPoint sets the function name of the entry point function for the script
func (e *Engine) SetEntryPoint(fnName string) {
e.EntryPoint = fnName
}
// LoadScriptWithTimeout evaluates an expression in the VM that honors the VMs timeout setting
func (e *Engine) LoadScriptWithTimeout(script *ast.Program) (otto.Value, error) {
start := time.Now()
defer e.recoveryHandler(start)
e.VM.Interrupt = make(chan func(), 1)
go e.timeoutMonitor()
return e.VM.Eval(script)
}
// CallFunctionWithTimeout calls a given top level function in the VM that honors the VMs timeout setting
func (e *Engine) CallFunctionWithTimeout(fn string) (otto.Value, error) {
start := time.Now()
defer e.recoveryHandler(start)
e.VM.Interrupt = make(chan func(), 1)
go e.timeoutMonitor()
return e.VM.Call(fn, nil, nil)
}
func (e *Engine) recoveryHandler(begin time.Time) {
duration := time.Since(begin)
if caught := recover(); caught != nil {
if caught == errTimeout {
e.Logger.Errorf("VM hit timeout after %v seconds", duration)
return
}
e.Logger.Errorf("VM encountered unexpected error: %v", caught)
return
}
return
}
func (e *Engine) timeoutMonitor() {
for {
time.Sleep(time.Duration(e.Timeout) * time.Second)
if !e.Paused {
e.VM.Interrupt <- func() {
panic(errTimeout)
}
return
} else {
continue
}
}
}