Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fix to prevent event machine from stopping when a raise is done in an unbind. #327

Open
wants to merge 1 commit into from

2 participants

@jochemsiegel

Currently, eventmachine will stop when a handler raises an exception in its unbind method. This is an intended feature for when the eventmachine reactor is being stopped, as it is undesirable to keep the reactor running when exceptions are being thrown while connections are being unbound.

This however does cause issues when exceptions are raised in unbinds when eventmachine is not being stopped.

This fix adds a method to the eventmachine cpp module which enables you to check wether or not the reactor is being stopped. Consequently the raising of an exception during an unbind will only resort in a reactor stop if it was already being stopped.

We implemented this locally for a project, tested it and it seems to be working well. Granted, this is only necessary if handler code implements exceptions in the unbind method.

Tests have been added, and the existing ones all still pass.

@jochemsiegel jochemsiegel Fix to prevent eventmachine from stopping when a raise is done in an …
…unbind.

Eventmachine IS stopped when an exception is raised while eventmachine
is stopping.
43d0ae5
@sodabrew sodabrew modified the milestone: v1.0.7, v1.2.0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on May 3, 2012
  1. @jochemsiegel

    Fix to prevent eventmachine from stopping when a raise is done in an …

    jochemsiegel authored
    …unbind.
    
    Eventmachine IS stopped when an exception is raised while eventmachine
    is stopping.
This page is out of date. Refresh to see the latest.
View
1  .gitignore
@@ -2,6 +2,7 @@ pkg
rdoc
Makefile
+*.idea
*.bundle
*.dll
*.so
View
9 ext/cmain.cpp
@@ -415,6 +415,15 @@ extern "C" void evma_stop_machine()
EventMachine->ScheduleHalt();
}
+/*****************
+evma_stopping
+*****************/
+
+extern "C" bool evma_stopping()
+{
+ ensure_eventmachine("evma_stopping");
+ return EventMachine->Stopping();
+}
/**************
evma_start_tls
View
5 ext/em.cpp
@@ -189,7 +189,10 @@ void EventMachine_t::ScheduleHalt()
bTerminateSignalReceived = true;
}
-
+bool EventMachine_t::Stopping()
+{
+ return bTerminateSignalReceived;
+}
/*******************************
EventMachine_t::SetTimerQuantum
View
1  ext/em.h
@@ -76,6 +76,7 @@ class EventMachine_t
void Run();
void ScheduleHalt();
+ bool Stopping();
void SignalLoopBreaker();
const unsigned long InstallOneshotTimer (int);
const unsigned long ConnectToServer (const char *, int, const char *, int);
View
1  ext/eventmachine.h
@@ -97,6 +97,7 @@ extern "C" {
void evma_set_max_timer_count (int);
void evma_setuid_string (const char *username);
void evma_stop_machine();
+ bool evma_stopping();
float evma_get_heartbeat_interval();
int evma_set_heartbeat_interval(float);
View
18 ext/rubymain.cpp
@@ -978,6 +978,23 @@ static VALUE t__ssl_p (VALUE self)
#endif
}
+/********
+t_stopping
+********/
+
+static VALUE t_stopping ()
+{
+ if (evma_stopping())
+ {
+ return Qtrue;
+ }
+ else
+ {
+ return Qfalse;
+ }
+
+}
+
/****************
t_send_file_data
@@ -1277,6 +1294,7 @@ extern "C" void Init_rubyeventmachine()
rb_define_module_function (EmModule, "kqueue?", (VALUE(*)(...))t__kqueue_p, 0);
rb_define_module_function (EmModule, "ssl?", (VALUE(*)(...))t__ssl_p, 0);
+ rb_define_module_function(EmModule, "stopping?",(VALUE(*)(...))t_stopping, 0);
rb_define_method (EmConnection, "get_outbound_data_size", (VALUE(*)(...))conn_get_outbound_data_size, 0);
rb_define_method (EmConnection, "associate_callback_target", (VALUE(*)(...))conn_associate_callback_target, 1);
View
7 lib/em/pure_ruby.rb
@@ -66,6 +66,11 @@ def run_machine
def release_machine
end
+
+ def stopping?
+ return Reactor.instance.stop_scheduled
+ end
+
# @private
def stop
Reactor.instance.stop
@@ -273,7 +278,7 @@ class Reactor
HeartbeatInterval = 2
- attr_reader :current_loop_time
+ attr_reader :current_loop_time, :stop_scheduled
def initialize
initialize_for_run
View
10 lib/eventmachine.rb
@@ -1441,9 +1441,13 @@ def self.event_callback conn_binding, opcode, data
rescue Errno::EBADF, IOError
end
end
- rescue
- @wrapped_exception = $!
- stop
+ rescue Exception => e
+ if stopping?
+ @wrapped_exception = $!
+ stop
+ else
+ raise e
+ end
end
elsif c = @acceptors.delete( conn_binding )
# no-op
View
17 tests/test_basic.rb
@@ -93,15 +93,28 @@ def unbind
end
end
- def test_unbind_error
+ def test_unbind_error_during_stop
assert_raises( UnbindError::ERR ) {
EM.run {
EM.start_server "127.0.0.1", @port
- EM.connect "127.0.0.1", @port, UnbindError
+ EM.connect "127.0.0.1", @port, UnbindError do
+ EM.stop
+ end
}
}
end
+ def test_unbind_error
+ EM.run {
+ EM.error_handler do |e|
+ assert(e.is_a?(UnbindError::ERR))
+ EM.stop
+ end
+ EM.start_server "127.0.0.1", @port
+ EM.connect "127.0.0.1", @port, UnbindError
+ }
+ end
+
module BrsTestSrv
def receive_data data
$received << data
Something went wrong with that request. Please try again.