Created
February 19, 2009 23:13
-
-
Save tmm1/67184 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/ext/rubymain.cpp b/ext/rubymain.cpp | |
| index 1e0dd6f..4eb7738 100644 | |
| --- a/ext/rubymain.cpp | |
| +++ b/ext/rubymain.cpp | |
| @@ -33,24 +33,36 @@ static VALUE EmConnection; | |
| static VALUE Intern_at_signature; | |
| static VALUE Intern_at_timers; | |
| static VALUE Intern_at_conns; | |
| +static VALUE Intern_at_error_handler; | |
| static VALUE Intern_event_callback; | |
| static VALUE Intern_run_deferred_callbacks; | |
| static VALUE Intern_delete; | |
| static VALUE Intern_call; | |
| static VALUE Intern_receive_data; | |
| static VALUE Intern_ssl_handshake_completed; | |
| - | |
| static VALUE Intern_notify_readable; | |
| static VALUE Intern_notify_writable; | |
| static VALUE rb_cProcStatus; | |
| +struct em_event { | |
| + const char *a1; | |
| + int a2; | |
| + const char *a3; | |
| + int a4; | |
| +}; | |
| + | |
| /**************** | |
| t_event_callback | |
| ****************/ | |
| -static void event_callback (const char *a1, int a2, const char *a3, int a4) | |
| +static void event_callback (struct em_event* e) | |
| { | |
| + const char *a1 = e->a1; | |
| + int a2 = e->a2; | |
| + const char *a3 = e->a3; | |
| + int a4 = e->a4; | |
| + | |
| if (a2 == EM_CONNECTION_READ) { | |
| VALUE t = rb_ivar_get (EmModule, Intern_at_conns); | |
| VALUE q = rb_hash_aref (t, rb_str_new2(a1)); | |
| @@ -93,7 +105,33 @@ static void event_callback (const char *a1, int a2, const char *a3, int a4) | |
| rb_funcall (EmModule, Intern_event_callback, 3, rb_str_new2(a1), (a2 << 1) | 1, rb_str_new(a3,a4)); | |
| } | |
| +/******************* | |
| +event_error_handler | |
| +*******************/ | |
| + | |
| +static void event_error_handler(void *, VALUE err) | |
| +{ | |
| + VALUE error_handler = rb_ivar_get(EmModule, Intern_at_error_handler); | |
| + rb_funcall (error_handler, Intern_call, 1, err); | |
| +} | |
| + | |
| +/********************** | |
| +event_callback_wrapper | |
| +**********************/ | |
| +static void event_callback_wrapper (const char *a1, int a2, const char *a3, int a4) | |
| +{ | |
| + struct em_event e; | |
| + e.a1 = a1; | |
| + e.a2 = a2; | |
| + e.a3 = a3; | |
| + e.a4 = a4; | |
| + | |
| + if (!rb_ivar_defined(EmModule, Intern_at_error_handler)) | |
| + event_callback(&e); | |
| + else | |
| + rb_rescue((VALUE (*)(ANYARGS))event_callback, (VALUE)&e, (VALUE (*)(ANYARGS))event_error_handler, NULL); | |
| +} | |
| /************************** | |
| t_initialize_event_machine | |
| @@ -101,7 +139,7 @@ t_initialize_event_machine | |
| static VALUE t_initialize_event_machine (VALUE self) | |
| { | |
| - evma_initialize_library (event_callback); | |
| + evma_initialize_library (event_callback_wrapper); | |
| return Qnil; | |
| } | |
| @@ -703,6 +741,7 @@ extern "C" void Init_rubyeventmachine() | |
| Intern_at_signature = rb_intern ("@signature"); | |
| Intern_at_timers = rb_intern ("@timers"); | |
| Intern_at_conns = rb_intern ("@conns"); | |
| + Intern_at_error_handler = rb_intern("@error_handler"); | |
| Intern_event_callback = rb_intern ("event_callback"); | |
| Intern_run_deferred_callbacks = rb_intern ("run_deferred_callbacks"); | |
| @@ -710,7 +749,6 @@ extern "C" void Init_rubyeventmachine() | |
| Intern_call = rb_intern ("call"); | |
| Intern_receive_data = rb_intern ("receive_data"); | |
| Intern_ssl_handshake_completed = rb_intern ("ssl_handshake_completed"); | |
| - | |
| Intern_notify_readable = rb_intern ("notify_readable"); | |
| Intern_notify_writable = rb_intern ("notify_writable"); | |
| diff --git a/lib/eventmachine.rb b/lib/eventmachine.rb | |
| index d355e1b..f9b415d 100644 | |
| --- a/lib/eventmachine.rb | |
| +++ b/lib/eventmachine.rb | |
| @@ -1165,7 +1165,19 @@ module EventMachine | |
| c | |
| end | |
| - | |
| + # Catch-all for errors raised during event loop callbacks. | |
| + # | |
| + # EM.error_handler{ |e| | |
| + # puts "Error raised during event loop: #{e.message}" | |
| + # } | |
| + # | |
| + def EventMachine::error_handler cb = nil, &blk | |
| + if cb or blk | |
| + @error_handler = cb || blk | |
| + elsif instance_variable_defined? :@error_handler | |
| + remove_instance_variable :@error_handler | |
| + end | |
| + end | |
| private | |
| def EventMachine::event_callback conn_binding, opcode, data | |
| diff --git a/tasks/tests.rake b/tasks/tests.rake | |
| index 81f3dea..af575b6 100644 | |
| --- a/tasks/tests.rake | |
| +++ b/tasks/tests.rake | |
| @@ -37,6 +37,7 @@ namespace :test do | |
| "test_basic.rb", | |
| "test_epoll.rb", | |
| "test_errors.rb", | |
| + "test_error_handler.rb", | |
| "test_eventables.rb", | |
| "test_exc.rb", | |
| "test_futures.rb", | |
| diff --git a/tests/test_error_handler.rb b/tests/test_error_handler.rb | |
| new file mode 100644 | |
| index 0000000..0bc9432 | |
| --- /dev/null | |
| +++ b/tests/test_error_handler.rb | |
| @@ -0,0 +1,32 @@ | |
| +$:.unshift "../lib" | |
| +require 'eventmachine' | |
| +require 'test/unit' | |
| + | |
| +class TestErrorHandler < Test::Unit::TestCase | |
| + def test_error_handler | |
| + error = nil | |
| + EM.error_handler{ |e| | |
| + error = e | |
| + EM.error_handler(nil) | |
| + EM.stop | |
| + } | |
| + | |
| + EM.run{ | |
| + EM.add_timer(0){ | |
| + raise 'test' | |
| + } | |
| + } | |
| + | |
| + assert_equal error.message, 'test' | |
| + end | |
| + | |
| + def test_without_error_handler | |
| + assert_raise RuntimeError do | |
| + EM.run{ | |
| + EM.add_timer(0){ | |
| + raise 'test' | |
| + } | |
| + } | |
| + end | |
| + end | |
| +end | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment