当进程内存不足时如何处理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 # 

如果我在debugging器下运行我的QJSEnginetesting应用程序(见下文),它会在V8代码中显示v8::internal::OS::DebugBreak调用。 如果我将调用QJSEngine::evaluate的代码QJSEngine::evaluate__try-__except ( SEH ),那么应用程序不会崩溃,但是这个解决scheme是Windows特有的。

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

=== QJSEnginetesting代码===

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

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

与SEH main.cpp(这不会崩溃,输出“致命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使用全局标志来logging是否发生致命错误。 一旦该标志被设置,V8将拒绝任何尝试创build新的JavaScript上下文,所以没有任何意义。 捕捉到最初的致命错误后,尝试执行一些良性的JavaScript代码。 如果我是对的,你会马上得到另一个致命的错误。

在我看来,正确的事情是Node和Qt将V8configuration为不会引起致命错误。 现在V8支持隔离和内存约束,处理查杀致命错误已经不合适了。 不幸的是,它看起来像V8的error handling代码还没有完全支持这些新function,并仍然假设内存不足的情况始终是不可恢复的。

Interesting Posts