2011-12-07 27 views
6

Tengo un problema similar al this other post y he intentado las soluciones dadas, pero fue en vano.¿Cómo se detectan las excepciones en una implementación de EventMachine?

Mi proyecto es un bot de Ruby que usa la biblioteca Blather para conectarse a un servidor Jabber. El problema es que cuando hay un problema con el servidor y Blather genera una excepción, todo el programa sale y no tengo oportunidad de detectar la excepción.

Aquí hay un código simple que muestra el problema. No hay un servidor Jabber ejecutándose en el host local, por lo que el cliente Blather arroja una excepción. Tenía la impresión de que EM.error_handler {} podría interceptarlo, pero nunca veo el mensaje **** ERROR y el programa simplemente se detiene. :(

#!/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 

Creo que el problema es que también utiliza blather EventMachine y tal vez está llamando EM.stop, lo que hace que la instancia EM externa para detener.

Respuesta

5

excepciones y programación asincrónica no son amigos, por lo que puede ser difícil de manejar correctamente. En el modelo síncrono, se puede capturar una excepción usando rescue en un bloque de código que puede producir excepciones, pero una vez que crea un método de devolución de llamada, ese bloque necesita su propio manejo de excepciones ya que se ejecutará de ese contexto.

Esperemos que el error_handler detectará su excepción, pero si tiene otros hilos implicados que pueden no ser capaces de capturarlos.

Siempre puede parchar en monopatín EventMachine.stop_event_loop y EventMachine.stop_server para ver si ese es el método al que se llama.

+0

Hmmm ... esta es una solución menos que óptima. 'error_handler' * debería * capturar estas cosas pero no es por alguna razón. Le daré una opción al parche de mono y veré si puedo "resolver" mi problema de esa manera. :/ –

+0

El parche de mono es solo para ver si se están llamando a esos métodos, ya que después de eso ya no son necesarios. – tadman

2

error_handler detecta excepciones que ocurren durante la ejecución de devoluciones de llamada activadas en el bucle de evento. No habrá iniciado el ciclo en el punto en que el código anterior está fallando. (Supongo que es Blather :: Stream.start en lugar de Blather :: Stream :: Client.start anterior).

Puede intentar hacer EM.next_tick {Blather :: Stream.start (...)} que lo forzará a ejecutar durante el ciclo del reactor.

Pero, en general, no desea continuar después de que el error_handler se haya disparado. Básicamente es una línea de última defensa para limpiar cualquier estado y salir (e imprimir un seguimiento de la pila para saber por qué se bloqueó la aplicación). Cuando se dispara, no tiene idea de cuál es el estado actual de su aplicación y realmente no puede confiar en que el estado sea correcto o coherente.

En teoría, sólo puede envolver la llamada blather en un comenzará/rescate:

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

¿Qué debe hacer el truco para usted, usted podría entonces se pega en alguna lógica de reintento.

Cuestiones relacionadas