2013-05-28 9 views
8
aus dem Speicher läuft

Beide node Konsole und QT5 V8-basierte QJSEngine durch den folgenden Code zum Absturz gebracht werden kann:Wie V8-Motor Absturz zu handhaben, wenn Prozess

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

Ausgang des Knotens vor Absturz:

FATAL ERROR: JS Allocation failed - process out of memory 

QJSEngine ‚s Ausgabe vor dem Absturz:

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

Wenn Ich starte meine QJSEngine Test-App (siehe unten) unter einem Debugger, es zeigt einen v8::internal::OS::DebugBreak Aufruf innerhalb des V8-Codes. Wenn ich den Code, der QJSEngine::evaluate aufruft, in __try-__except (SEH) verpacken, wird die App nicht abstürzen, aber diese Lösung ist Windows-spezifisch.

Frage: Gibt es eine Möglichkeit v8::internal::OS::DebugBreak in einer Plattform-unabhängigen Weise in Knoten- und Qt-Anwendungen zu behandeln?

=== QJSEngine Testcode ===

Entwicklungsumgebung: QtCreator mit QT5 und Windows SDK 7.1, auf Windows XP SP3

QJSEngineTest.pro:

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

Haupt .cpp ohne SEH (dies stürzt ab):

#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 mit SEH (dies wird nicht abstürzen, gibt „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; 
} 

Antwort

3

Ich glaube nicht, gibt es eine plattformübergreifende Art und Weise fatale Fehler abzufangen V8, aber selbst wenn es gab, oder wenn es eine Möglichkeit gibt, sie auf allen Plattformen, die dir wichtig sind, zu fangen, bin ich mir nicht sicher, was das für dich bedeuten würde.

Das Problem ist, dass V8 global flag verwendet, die aufzeichnet, ob ein schwerwiegender Fehler aufgetreten ist. Sobald dieses Flag gesetzt ist, wird V8 jeden Versuch, neue JavaScript-Kontexte zu erstellen, ablehnen, so dass es sowieso keinen Sinn macht, weiterzumachen. Versuchen Sie, nach dem Auffangen des ersten schwerwiegenden Fehlers einen gutartigen JavaScript-Code auszuführen. Wenn ich recht habe, wirst du sofort einen weiteren fatalen Fehler bekommen.

Meiner Meinung nach wäre es das Richtige für Node und Qt, V8 so zu konfigurieren, dass keine schwerwiegenden Fehler ausgelöst werden. Da nun V8 Isolierungen und Speicherbeschränkungen unterstützt, sind fatale Fehler bei der Prozessauslöschung nicht mehr angemessen. Unglücklicherweise sieht es so aus, als ob der Fehlerbehandlungscode von V8 diese neueren Funktionen noch nicht vollständig unterstützt und immer noch mit der Annahme arbeitet, dass Speicherbedingungen immer nicht behebbar sind.

+0

Beachten Sie außerdem, dass Sie einen Rückruf kurz vor dem Abbruch mithilfe von V8 :: SetFatalErrorHandler() registrieren können. Dies bietet Ihnen jedoch weiterhin nicht die Möglichkeit, den v8-Stapel abzuwickeln. Sie können OS :: Abort() auch mit --no-hard_abort steuern, damit der Prozess ruhig (SIGABRT) und nicht mit einer Zugriffsverletzung (V8_IMMEDIATE_CRASH()) beendet wird. (Ich bin mir nicht sicher, unter welchen Umständen DebugBreak() aufgerufen wird - möglicherweise nur, wenn ein Debugger angehängt ist.) –