2010-08-24 24 views
5

Tôi đang làm việc trên thư viện nơi tôi đang triển khai nhiều tác vụ khác nhau cho một số thư viện của bên thứ ba. (Cụ thể, tôi đang viết một trình phân tích hàm toán học gọi các trình biên dịch JIT, như LLVM hoặc libjit, để xây dựng mã máy.) Trong thực tế, các thư viện của bên thứ ba này có xu hướng bị lỗi (một phần của đây là lỗi của tôi) , tất nhiên, nhưng tôi vẫn muốn một số bảo hiểm).Làm cách nào để cách nhiệt một công việc/chủ đề từ các sự cố

Tôi muốn, sau đó, để có thể rất duyên dáng đối phó với một công việc chết khủng khiếp - SIGSEGV, SIGILL, v.v. - mà không mang xuống phần còn lại của mã của tôi (hoặc mã của người sử dụng gọi điện thoại của tôi chức năng thư viện). Để rõ ràng, tôi không quan tâm nếu công việc cụ thể đó có thể tiếp tục (tôi sẽ không cố gắng sửa chữa một tình trạng tai nạn), tôi cũng không quan tâm đến trạng thái của các đối tượng sau vụ tai nạn đó (tôi sẽ hủy bỏ chúng ngay lập tức nếu có sự cố). Tôi chỉ muốn có thể phát hiện thấy một vụ tai nạn đã xảy ra, dừng vụ tai nạn từ việc loại bỏ toàn bộ quá trình, ngừng gọi bất kỳ sự cố nào xảy ra và tiếp tục thực hiện.

(Đối với một ít ngữ cảnh hơn, mã tại thời điểm này là vòng lặp for, kiểm tra từng trình biên dịch JIT có sẵn. Một số trình biên dịch này có thể bị lỗi. Nếu có, tôi chỉ muốn thực thi continue; và tiếp tục với thử nghiệm một trình biên dịch khác.)

Hiện tại, tôi đã thực hiện dựa trên signal() không thành công lắm; tất nhiên, đó là hành vi không xác định đối với longjmp() trong bộ xử lý tín hiệu và các trình xử lý tín hiệu được dự kiến ​​sẽ kết thúc với exit() hoặc terminate(). Chỉ cần ném mã trong một chủ đề khác không giúp đỡ chính nó, ít nhất là cách tôi đã thử nghiệm nó cho đến nay. Tôi cũng không thể hack ra một cách để làm cho công việc này bằng cách sử dụng ngoại lệ C++.

Vì vậy, cách tốt nhất để cách nhiệt một tập hợp lệnh/chuỗi/công việc cụ thể khỏi sự cố là gì?

Trả lời

10

Tạo ra một quy trình mới.

+1

Đây là cách duy nhất để làm điều đó. Một luồng có thể làm hỏng bộ nhớ ở bất kỳ nơi nào trong tiến trình, vì vậy sau SEGV, bạn không thể đảm bảo rằng bộ nhớ của bạn không bị ảnh hưởng. – KeithB

+0

Cảm ơn bạn đã trưởng thành. Gần như chắc chắn là câu trả lời đúng ở đây. Tôi đi đọc trên fork() và công ty. –

5

Bạn thu thập kết quả nào khi công việc thành công?

Tôi hỏi vì nếu đầu ra là băng thông thấp, tôi sẽ bị cám dỗ để chạy từng công việc trong quy trình riêng của mình.

Mỗi công việc trong số những tác vụ bị lỗi mà bạn kích hoạt có khả năng làm hỏng bộ nhớ được sử dụng ở nơi khác trong quy trình của bạn.

Quy trình cung cấp sự bảo vệ tốt nhất.

1

Quy trình cung cấp sự bảo vệ tốt nhất, nhưng có thể bạn không thể làm điều đó.

Nếu điểm nhập của chủ đề là các hàm bạn đã viết, (ví dụ: ThreadProc trong thế giới Windows), thì bạn có thể bọc chúng trong các khối try{...}catch(...). Nếu bạn muốn giao tiếp rằng một ngoại lệ đã xảy ra, thì bạn có thể giao tiếp các mã lỗi cụ thể về chủ đề chính hoặc sử dụng một số cơ chế khác. Nếu bạn muốn đăng nhập không chỉ là một ngoại lệ đã xảy ra nhưng ngoại lệ đó là gì, thì bạn sẽ cần phải nắm bắt các loại ngoại lệ cụ thể và trích xuất thông tin chẩn đoán từ chúng để truyền lại cho luồng chính. A'la:

int my_tempermental_thread() 
{ 
    try 
    { 
    // ... magic happens ... 
    return 0; 
    } 
    catch(const std::exception& ex) 
    { 
    // ... or maybe it doesn't ... 
    string reason = ex.what(); 
    tell_main_thread_what_went_wong(reason); 
    return 1; 
    } 
    catch(...) 
    { 
    // ... definitely not magical happenings here ... 
    tell_main_thread_what_went_wrong("uh, something bad and undefined"); 
    return 2; 
    } 
} 

Lưu ý rằng nếu bạn đi theo cách này, bạn có nguy cơ gây ra quá trình lưu trữ khi xảy ra ngoại lệ. Bạn nói rằng bạn không cố gắng sửa chữa vấn đề, nhưng làm thế nào để bạn biết các chủ đề ác tính không ăn stack của bạn ví dụ? Bắt-và-bỏ qua là một cách tuyệt vời để tạo ra các lỗi khủng khiếp gây nhầm lẫn.

0

Trên Windows, bạn có thể sử dụng VirtualProtect(YourMemory, PAGE_READONLY) khi gọi mã không đáng tin cậy. Bất kỳ nỗ lực nào để sửa đổi bộ nhớ này sẽ gây ra Ngoại lệ có cấu trúc. Bạn có thể nắm bắt điều này một cách an toàn và tiếp tục thực hiện. Tuy nhiên, bộ nhớ được phân bổ bởi thư viện đó tất nhiên sẽ bị rò rỉ, cũng như các tài nguyên khác. Tương đương với Linux là mprotect(YorMemory, PROT_READ), gây ra SEGV.

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