2013-05-28 25 views
8

Cả node console và Qt5 của V8 dựa trên QJSEngine có thể bị rơi bởi đoạn mã sau: sản lượngLàm thế nào để xử lý vụ tai nạn cơ V8 khi quá trình chạy ra khỏi bộ nhớ

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

nút trước khi vụ tai nạn:

FATAL ERROR: JS Allocation failed - process out of memory 

Đầu ra của QJSEngine trước khi tai nạn:

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

Nếu Tôi chạy ứng dụng thử nghiệm QJSEngine của mình (xem bên dưới) dưới trình gỡ lỗi, nó hiển thị cuộc gọi v8::internal::OS::DebugBreak bên trong mã V8. Nếu tôi quấn mã gọi QJSEngine::evaluate vào __try-__except (SEH), thì ứng dụng sẽ không gặp sự cố, nhưng giải pháp này dành riêng cho Windows.

Câu hỏi: Có cách nào để xử lý v8::internal::OS::DebugBreak theo cách không phụ thuộc vào nền tảng trong các ứng dụng nút và Qt không?

=== mã kiểm tra QJSEngine ===

môi trường phát triển: QtCreator với Qt5 và Windows SDK 7.1, trên Windows XP SP3

QJSEngineTest.pro:

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

chính .cpp không có SEH (điều này sẽ bị lỗi):

#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 với SEH (điều này sẽ không sụp đổ, kết quả đầu ra "ngoại lệ Fatal"):

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

Trả lời

3

Tôi không tin rằng có một cách nền tảng để bẫy V8 lỗi gây tử vong, nhưng ngay cả khi đã có, hoặc nếu có cách nào đó để bẫy chúng trên tất cả các nền tảng mà bạn quan tâm, tôi không chắc nó sẽ mua gì cho bạn.

Vấn đề là V8 sử dụng global flag ghi lại liệu có xảy ra lỗi nghiêm trọng hay không. Khi cờ đó được đặt, V8 sẽ từ chối bất kỳ nỗ lực nào để tạo ngữ cảnh JavaScript mới, do đó, không có bất kỳ điểm nào trong việc tiếp tục. Hãy thử thực hiện một số mã JavaScript lành tính sau khi bắt lỗi nghiêm trọng ban đầu. Nếu tôi đúng, bạn sẽ nhận được một lỗi nghiêm trọng khác ngay lập tức.

Theo ý kiến ​​của tôi, điều đúng đắn là cho Node và Qt định cấu hình V8 để không gây ra lỗi nghiêm trọng ngay từ đầu. Giờ đây, V8 hỗ trợ sự cô lập và hạn chế về bộ nhớ, lỗi giết chết quá trình giết chết không còn phù hợp nữa. Rất tiếc, có vẻ như mã xử lý lỗi của V8 chưa hỗ trợ đầy đủ các tính năng mới hơn và vẫn hoạt động với giả định rằng các điều kiện ngoài bộ nhớ luôn không thể khôi phục.

+0

Cũng lưu ý rằng bạn có thể đăng ký gọi lại ngay trước khi hủy sử dụng V8 :: SetFatalErrorHandler(), mặc dù điều này vẫn không cung cấp cho bạn khả năng thư giãn ngăn xếp v8. Bạn cũng có thể kiểm soát OS :: Abort() bằng --no-hard_abort để làm cho quá trình thoát ra lặng lẽ (SIGABRT) thay vì vi phạm quyền truy cập (V8_IMMEDIATE_CRASH()). (Tôi không chắc chắn trong trường hợp nào DebugBreak() được gọi - chỉ có thể là khi một trình sửa lỗi được đính kèm.) –

Các vấn đề liên quan