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



节点控制台和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-__except (SEH),那么应用程序就不会崩溃,但这种解决方案是特定于windows的。

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

=== QJSEngine测试代码===

开发环境:QtCreator with Qt5 and Windows SDK 7.1, on Windows XP SP3

QJSEngineTest.pro:

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

main.cpp不带SEH(这会崩溃):

#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;
}

main.cpp with SEH(这不会崩溃,输出"Fatal exception"):

#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;
}

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

问题是V8使用一个全局标志来记录是否发生了致命错误。一旦设置了这个标志,V8将拒绝任何创建新的JavaScript上下文的尝试,所以继续下去没有任何意义。在捕捉到最初的致命错误后,尝试执行一些无害的JavaScript代码。如果我是对的,你马上就会得到另一个致命错误。

在我看来,正确的事情是让Node和Qt配置V8,首先不要引发致命错误。现在V8支持隔离和内存约束,杀死进程的致命错误不再合适。不幸的是,看起来V8的错误处理代码还没有完全支持这些新特性,并且仍然假设内存不足的情况总是不可恢复的。

相关内容

  • 没有找到相关文章

最新更新