Как справиться с аварией двигателя 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::internal::OS::DebugBreak Звоните внутри кода V8. Если я заверну код вызова QJSEngine::evaluate в __try-__except ( SEH), тогда приложение не будет аварийно завершено, но это решение зависит от Windows.

Вопрос: есть ли способ справиться v8::internal::OS::DebugBreak независимым от платформы образом в приложениях узлов и Qt?

=== QJSEngine тестовый код ===

Среда разработки: QtCreator с Qt5 и Windows SDK 7.1, в 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 с SEH (это не приводит к сбою, выводит "Фатальное исключение"):

#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 ответ

Решение

Я не верю, что есть кроссплатформенный способ отловить фатальные ошибки V8, но даже если бы они были, или если бы был какой-то способ отловить их на всех платформах, которые вас волнуют, я не уверен, что это купит вас,

Проблема в том, что V8 использует глобальный флаг, который записывает, произошла ли фатальная ошибка. Как только этот флаг установлен, V8 будет отклонять любые попытки создания новых контекстов JavaScript, так что нет никакого смысла продолжать в любом случае. Попробуйте выполнить некий доброкачественный код JavaScript после обнаружения исходной фатальной ошибки. Если я прав, вы сразу же получите еще одну фатальную ошибку.

На мой взгляд, для Node и Qt правильнее было бы настроить V8, чтобы в первую очередь не вызывать фатальных ошибок. Теперь, когда V8 поддерживает изоляты и ограничения памяти, фатальные ошибки, убивающие процессы, больше не подходят. К сожалению, похоже, что код обработки ошибок V8 еще не полностью поддерживает эти новые функции, и все еще работает с допущением, что условия нехватки памяти всегда неисправимы.

Другие вопросы по тегам