当进程内存不足时如何处理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器下运行我的QJSEngine
testing应用程序(见下文),它会在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,并仍然假设内存不足的情况始终是不可恢复的。