我正在使用Google的v8引擎在我的应用程序中嵌入javascript。在某些时候,我将调用用户提供的代码,我想通过分配太多内存来确保它不会表现不好。目前,当javascript尝试将数组调大或调整为太大时,例如,我收到一条毫不客气的消息:
#
# Fatal error in CALL_AND_RETRY_LAST
# Allocation failed - process out of memory
#
然后整个过程与SIGILL崩溃。显然,这是不可接受的。我需要能够运行用户提供的代码,但是......在引擎执行之前手动审核所有代码是不可行的。
在这种情况下,我理想的做法是简单地终止占用过多内存的隔离区(不影响可能正在运行的任何其他隔离区)。是否有任何方法可以指定js程序在失败之前允许使用的最大内存量,因此如果它超过了该限制,而不是使进程崩溃,则调用Run或Call命令只会返回错误或设置一些状态标志,表明它已异常终止。
到目前为止我尝试过的事情:
在创建隔离时设置自定义array_buffer分配器,该隔离器跟踪正在使用多少内存,并在内存使用率过高时终止隔离>我的分配器的Allocate功能永远不会被调用。
使用跟踪内存使用情况的函数调用AddMemoryAllocationCallback,并在分配超过一定数量时尝试通过TerminateExecution()终止隔离。这个函数确实被调用了,但是在这个函数报告了几兆字节之后我得到了一个内存不足的错误,而我知道由坏行为v8函数创建的数据是 FAR < / em>大于那个。
通过SetFatalErrorHandler设置致命错误处理程序并尝试在那里调用TerminateExecution。此函数会被调用,但不会阻止进程崩溃。
还有什么我可以尝试的吗?
答案 0 :(得分:1)
编辑:来自V8团队的权威回复 - 您无法做到。但他们会接受补丁。
v8 :: Isolate :: SetFatalErrorHandler()应该允许你不崩溃。但是,我的理解是隔离在事后仍然无法使用。可能无法解决这个问题,因为隔离区将处于不可恢复的状态。
http://v8.paulfryzel.com/docs/master/classv8_1_1_isolate.html#a131f1e2e6a80618ac3c8c266a041851d
(也许。在2013-2014期间似乎有很多关于这个问题的事情,谷歌的人说正确的做法是让v8杀死这个过程 - 很多人都在这个过程中我觉得很愚蠢。我没有看到任何解决方案)
编辑:邮件列表响应是你无法做到这一点。如果它不会对性能产生影响,他们会接受补丁。
编辑:这里只有另一个帖子,有人发布了一些在非恶意情况下避免OOM的好方法:
https://groups.google.com/forum/#!topic/v8-users/vKn1hVs8KNQ
我将堆限制设置为我实际想要的限制的8倍。然后,每次之后 调用隔离,我检查内存使用情况是否超过了 预期限制。如果是这样,我调用垃圾收集。如果仍 在此之后超过限制,然后我在那时终止隔离。
同时,我们还强制执行50毫秒的CPU时间限制。在实践中,a 分配大量内存的脚本往往会耗尽CPU时间 在它达到8x堆限制之前(特别是当GC减慢速度时) 接近极限时下降。)