展开目录
otto踩坑:vm.Interrupt导致goroutine无限增加
golangotto
X
陈尼玛的博客
记录开发生涯的踩坑经历,用时间来验证成长
加载中

otto是golang的js虚拟机,基本支持正常的js代码,但re2或者es6这些现代化特性暂不支持。由于是虚拟机,因此需要限制脚本运行最长时间,从官网了解到限制的方法:

package main

import (
    "errors"
    "fmt"
    "os"
    "time"

    "github.com/robertkrimen/otto"
)

var halt = errors.New("Stahp")

func main() {
    runUnsafe(`var abc = [];`)
    runUnsafe(`
    while (true) {
        // Loop forever
    }`)
}

func runUnsafe(unsafe string) {
    start := time.Now()
    defer func() {
        duration := time.Since(start)
        if caught := recover(); caught != nil {
            if caught == halt {
                fmt.Fprintf(os.Stderr, "Some code took to long! Stopping after: %v\n", duration)
                return
            }
            panic(caught) // Something else happened, repanic!
        }
        fmt.Fprintf(os.Stderr, "Ran code successfully: %v\n", duration)
    }()

    vm := otto.New()
    vm.Interrupt = make(chan func(), 1) // The buffer prevents blocking

    go func() {
        time.Sleep(2 * time.Second) // Stop after two seconds
        vm.Interrupt <- func() {
            panic(halt)
        }
    }()

    vm.Run(unsafe) // Here be dragons (risky code)
}

这种方法对应超时的脚本不会产生问题,然而,如果这个脚本正常跑完了,那么推入Interrupt里的 东西就不会被拉出来,从而导致goroutine一直不被释放。

因此这种写法还需要增加一个容错处理,我修改之后如下:


...
    // 增加一个额外的状态,如果otto没有自动拉出来,那么就在正常结束时我来处理
    state := make(chan int,1)
    state<-0

    go func() {
      if <-state==0 {
        state<-2
        time.Sleep(2 * time.Second) // Stop after two seconds
        vm.Interrupt <- func() {
            panic(halt)
        }
      }
    }()

    vm.Run(unsafe) // Here be dragons (risky code)

    // 超过时间也会执行到这里,如果没有超过时间,那么取出的是0,否则取出的是2
    if <-state==0{state<-1}
    close(state)
...

相关文档

暂无

随便看看

  1. 定长消息队列读写优化

  2. react项目webpack打包时拆分异步加载的文件

  3. nginx 子域名对应文件夹

  4. raw.githubusercontent.com DNS被指向127.0.0.1

  5. css3 文字渐变色

  6. npm远程服务器某些配置不兼容代理的解决办法

  7. curl用法

  8. SSL certificate problem: self signed certificate in certificate chain

  9. nodejs socks5

  10. heroku查看app使用时间

  11. heroku登陆cli

  12. npm设置仓库地址和代理

  13. webrtc泄漏本地ip信息

  14. 树莓派 3B/3B+ usb启动

  15. ssl 证书生成方式

  16. sendmail用nginx做代理

  17. replace2正则扩展方法

  18. ie8上Image.onload不触发问题

  19. bootstrap modal弹框导致ie无法获取焦点

畅言模块加载中