当进程内存不足时,如何处理V8引擎崩溃

时间:2013-05-28 16:51:45

标签: node.js v8 qt5 seh debugbreak

node控制台和Qt5的基于V8的QJSEngine都可以通过以下代码崩溃:

a = []; for (;;) { a.push("hello"); }

崩溃前节点的输出:

FATAL ERROR: JS Allocation failed - process out of memory
崩溃前

QJSEngine的输出:

#
# Fatal error in JS
# Allocation failed - process out of memory
#

如果我在调试器下运行我的QJSEngine测试应用程序(见下文),它会在V8代码中显示v8::internal::OS::DebugBreak调用。如果我将调用QJSEngine::evaluate的代码包装到__try-__exceptSEH)中,那么应用程序不会崩溃,但此解决方案是特定于Windows的。

问题:有没有办法在节点和Qt应用程序中以独立于平台的方式处理v8::internal::OS::DebugBreak

=== QJSEngine测试代码===

开发环境:Qt5和Windows SDK 7.1的QtCreator,在Windows XP SP3上

QJSEngineTest.pro:

TEMPLATE = app
QT -= gui
QT += core qml
CONFIG -= app_bundle
CONFIG += console
SOURCES += main.cpp
TARGET = QJSEngineTest
没有SEH的

main.cpp(这会崩溃):

#include <QtQml/QJSEngine>

int main(int, char**)
{
  try {
    QJSEngine engine;
    QJSValue value = engine.evaluate("a = []; for (;;) { a.push('hello'); }");
    qDebug(value.isError() ? "Error" : value.toString().toStdString().c_str());
  } catch (...) {
    qDebug("Exception");
  }
  return 0;
}

带有SEH的main.cpp(这不会崩溃,输出“致命异常”):

#include <QtQml/QJSEngine>
#include <Windows.h>

void runTest()
{
  try {
    QJSEngine engine;
    QJSValue value = engine.evaluate("a = []; for (;;) { a.push('hello'); }");
    qDebug(value.isError() ? "Error" : value.toString().toStdString().c_str());
  } catch (...) {
    qDebug("Exception");
  }
}

int main(int, char**)
{
  __try {
    runTest();
  } __except(EXCEPTION_EXECUTE_HANDLER) {
    qDebug("Fatal exception");
  }
  return 0;
}

1 个答案:

答案 0 :(得分:3)

我不相信有一种跨平台的方法来捕获V8致命错误,但即使有,或者如果有某种方法将它们捕获到你关心的所有平台上,我也不确定那是什么会买你的。

问题是V8使用global flag来记录是否发生了致命错误。一旦设置了该标志,V8将拒绝任何创建新JavaScript上下文的尝试,因此无论如何都没有意义继续。在捕获初始致命错误后尝试执行一些良性JavaScript代码。如果我是对的,你马上就会得到另一个致命的错误。

在我看来,正确的是Node和Qt将V8配置为不首先引发致命错误。既然V8支持隔离和内存约束,那么杀死致命错误的进程就不再合适了。不幸的是,看起来V8的错误处理代码还没有完全支持这些较新的功能,并且仍然假设内存不足的情况总是无法恢复。