Skip to content
Permalink
Browse files

Isolate terminate execution (#5)

* terminate any long running scripts

* siplifiy test

* update the readme with a termination example
  • Loading branch information...
rogchap committed Sep 7, 2019
1 parent 79ca726 commit 00d2f882ab66f6b671f74377df30d5f190178293
Showing with 77 additions and 7 deletions.
  1. +28 −0 README.md
  2. +3 −5 errors.go
  3. +6 −0 isolate.go
  4. +33 −0 isolate_test.go
  5. +6 −1 v8go.cc
  6. +1 −1 v8go.h
@@ -50,6 +50,34 @@ if err != nil {
}
```

### Terminate long running scripts

```go
vals := make(chan *v8go.Value, 1)
errs := make(chan error, 1)
go func() {
val, err := ctx.RunScript(script, "forever.js") // exec a long running script
if err != nil {
errs <- err
return
}
vals <- val
}()
select {
case val := <- vals:
// sucess
case err := <- errs:
// javascript error
case <- time.After(200 * time.Milliseconds):
vm, _ := ctx.Isolate() // get the Isolate from the context
vm.TerminateExecution() // terminate the execution
err := <- errs // will get a termination error back from the running script
}
```

## Documentation

GoDoc: https://godoc.org/rogchap.com/v8go
@@ -23,11 +23,9 @@ func (e *JSError) Error() string {
func (e *JSError) Format(s fmt.State, verb rune) {
switch verb {
case 'v':
if s.Flag('+') {
if e.StackTrace != "" {
io.WriteString(s, e.StackTrace)
return
}
if s.Flag('+') && e.StackTrace != "" {
io.WriteString(s, e.StackTrace)
return
}
fallthrough
case 's':
@@ -30,6 +30,12 @@ func NewIsolate() (*Isolate, error) {
return iso, nil
}

// Forcefully terminate the current thread of JavaScript execution
// in the given isolate.
func (i *Isolate) TerminateExecution() {
C.IsolateTerminateExecution(i.ptr)
}

func (i *Isolate) finalizer() {
C.IsolateDispose(i.ptr)
i.ptr = nil
@@ -0,0 +1,33 @@
package v8go_test

import (
"strings"
"testing"
"time"

"rogchap.com/v8go"
)

func TestIsolateTermination(t *testing.T) {
t.Parallel()
iso, _ := v8go.NewIsolate()
ctx, _ := v8go.NewContext(iso)
// ctx2, _ := v8go.NewContext(iso)

err := make(chan error, 1)

go func() {
_, e := ctx.RunScript(`while (true) { }`, "forever.js")
err <- e
}()

go func() {
// [RC] find a better way to know when a script has started execution
time.Sleep(time.Millisecond)
iso.TerminateExecution()
}()

if e := <-err; e == nil || !strings.HasPrefix(e.Error(), "ExecutionTerminated") {
t.Errorf("unexpected error: %v", e)
}
}
@@ -51,6 +51,11 @@ RtnError ExceptionError(TryCatch& try_catch, Isolate* iso, Local<Context> ctx) {

RtnError rtn = {nullptr, nullptr, nullptr};

if (try_catch.HasTerminated()) {
rtn.msg = "ExecutionTerminated: script execution has been terminated";
return rtn;
}

String::Utf8Value exception(iso, try_catch.Exception());
rtn.msg = CopyString(exception);

@@ -104,7 +109,7 @@ void IsolateDispose(IsolatePtr ptr) {
iso->Dispose();
}

void TerminateExecution(IsolatePtr ptr) {
void IsolateTerminateExecution(IsolatePtr ptr) {
Isolate* iso = static_cast<Isolate*>(ptr);
iso->TerminateExecution();
}
2 v8go.h
@@ -22,7 +22,7 @@ typedef struct {
extern void Init();
extern IsolatePtr NewIsolate();
extern void IsolateDispose(IsolatePtr ptr);
extern void TerminateExecution(IsolatePtr ptr);
extern void IsolateTerminateExecution(IsolatePtr ptr);

extern ContextPtr NewContext(IsolatePtr prt);
extern void ContextDispose(ContextPtr ptr);

0 comments on commit 00d2f88

Please sign in to comment.
You can’t perform that action at this time.