2011-12-07 35 views
6

Tôi gặp sự cố tương tự với this other post và tôi đã thử các giải pháp đã cho nhưng không có kết quả.Làm thế nào để bạn nắm bắt ngoại lệ trong một cài đặt EventMachine?

Dự án của tôi là rô bốt Ruby sử dụng thư viện Blather để kết nối với máy chủ Jabber. Vấn đề là khi có một vấn đề với máy chủ và Blather tạo ra một ngoại lệ toàn bộ chương trình thoát và tôi không có cơ hội để bắt ngoại lệ.

Dưới đây là một số mã đơn giản hiển thị sự cố. Không có máy chủ Jabber nào chạy trên máy chủ cục bộ để máy khách Blather ném một ngoại lệ. Tôi đã được ấn tượng rằng EM.error_handler {} sẽ có thể đánh chặn nó nhưng tôi không bao giờ thấy thông báo **** ERROR và chương trình chỉ dừng lại. :(

#!/usr/bin/env ruby 
require 'rubygems' 
require 'blather/client/client' 

EM.run do 
    EM.error_handler { puts " **** ERROR " } 

    Blather::Stream::Client.start(
    Class.new { 
    }.new, '[email protected]', 'echo') 
end 

Tôi nghĩ vấn đề là Blather cũng sử dụng EventMachine và có thể được gọi EM.stop, gây ra các trường hợp EM bên ngoài để ngăn chặn.

Trả lời

5

Exceptions và lập trình không đồng bộ không phải là bạn bè, vì vậy họ Trong mô hình đồng bộ, một ngoại lệ có thể bị bắt bằng cách sử dụng rescue trên một khối mã có thể tạo ra ngoại lệ, nhưng khi bạn tạo phương thức gọi lại, khối đó cần xử lý ngoại lệ riêng vì nó sẽ chạy bên ngoài trong bối cảnh đó.

Hy vọng rằng error_handler sẽ bắt ngoại lệ của bạn, nhưng nếu bạn có các chủ đề khác liên quan mà có thể không có khả năng nắm bắt chúng.

Bạn luôn có thể monkeypatch EventMachine.stop_event_loopEventMachine.stop_server để xem đó có phải là phương pháp được gọi hay không.

+0

Hmmm ... đây là giải pháp ít hơn tối ưu. 'error_handler' * nên * bắt được những thứ này nhưng không phải vì lý do nào đó. Tôi sẽ cung cấp cho các tùy chọn vá khỉ một đi và xem nếu tôi có thể "giải quyết" vấn đề của tôi theo cách đó. :/ –

+0

Bản vá khỉ chỉ để xem liệu các phương pháp đó có đang được gọi hay không, vì sau đó chúng không còn cần thiết nữa. – tadman

2

Error_handler bắt ngoại lệ xảy ra trong khi thực hiện cuộc gọi lại được kích hoạt trong vòng lặp sự kiện. Bạn sẽ không bắt đầu vòng lặp tại điểm mã trên bị lỗi. (Tôi giả định đó là Blather :: Stream.start thay vì Blather :: Stream :: Client.start ở trên).

Bạn có thể thử thực hiện EM.next_tick {Blather :: Stream.start (...)} để buộc nó thực hiện trong vòng lặp của lò phản ứng.

Nhưng nói chung, bạn không muốn tiếp tục sau khi error_handler kích hoạt. Về cơ bản nó là một tuyến phòng thủ cuối cùng để bạn dọn dẹp bất kỳ trạng thái và lối ra nào (và in dấu vết ngăn xếp để bạn biết tại sao ứng dụng bị lỗi). Khi nó cháy bạn không biết trạng thái hiện tại của ứng dụng của bạn là gì và bạn có thể không thực sự tin tưởng trạng thái là chính xác hoặc nhất quán.

Về lý thuyết, bạn chỉ có thể quấn gọi Blather trong một bắt đầu/cứu hộ:

begin 
    Blather::Stream.start(...) 
rescue Exception => e 
    puts e 
end 

nào nên làm các trick cho bạn, sau đó bạn có thể dính vào một số logic thử lại.

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