Как вы ловите исключения в реализации EventMachine? - PullRequest
6 голосов
/ 07 декабря 2011

У меня проблема, аналогичная этому другому посту , и я попробовал данные решения, но безрезультатно.

Мой проект - бот Ruby, который использует библиотеку Blather для подключения к серверу Jabber. Проблема в том, что когда возникает проблема с сервером, и Blather генерирует исключение, вся программа завершается, и у меня нет возможности перехватить исключение.

Вот простой код, который показывает проблему. На localhost не работает Jabber-сервер, поэтому клиент Blather генерирует исключение. У меня сложилось впечатление, что EM.error_handler {} сможет его перехватить, но я никогда не вижу сообщения **** ERROR, и программа просто останавливается. (

#!/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, 'echo@127.0.0.1', 'echo')
end

Думаю, проблема в том, что Blather также использует EventMachine и, возможно, вызывает EM.stop, что приводит к остановке внешнего экземпляра EM.

Ответы [ 3 ]

5 голосов
/ 07 декабря 2011

Исключения и асинхронное программирование не дружат, поэтому с ними может быть сложно справиться должным образом. В синхронной модели исключение может быть перехвачено с помощью rescue в блоке кода, который может генерировать исключения, но после создания метода обратного вызова этот блок нуждается в собственной обработке исключений, поскольку он будет работать вне этого контекста. 1002 *

Надеемся, что error_handler поймает ваше исключение, но если у вас есть другие потоки, которые могут быть не в состоянии перехватить их.

Вы всегда можете установить monkeypatch EventMachine.stop_event_loop и EventMachine.stop_server, чтобы узнать, вызывается ли этот метод.

2 голосов
/ 15 декабря 2011

Обработчик ошибок ловит исключения, возникающие во время выполнения обратных вызовов, запускаемых в цикле событий.Вы не запустили цикл в тот момент, когда вышеприведенный код дает сбой.(Я предполагаю, что это Blather :: Stream.start вместо Blather :: Stream :: Client.start выше).

Вы можете попробовать сделать EM.next_tick {Blather :: Stream.start (...)}, что заставит его выполняться во время цикла реактора.

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

Теоретически вы можете просто обернуть вызов Blather в начале/ rescue:

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

Что должно помочь вам, тогда вы можете придерживаться некоторой логики повторения.

1 голос
/ 04 июня 2019

Вы можете прикрепить error_handler таким образом:

require 'eventmachine'

EM.run do
  # your stuff
end

# Outside `EM.run`
EM.error_handler do |e|
  # Then you can do something like these:
  puts e.message
  puts e.inspect
  puts e.backtrace.join("\n")
end
...