Permalink
Browse files

Allow Rubinius to cleanup handles/objects properly

  • Loading branch information...
1 parent 7497dd1 commit 72e9fc232d99e544aaba51df67de1fe01f27f565 Evan Phoenix committed May 13, 2011
Showing with 47 additions and 8 deletions.
  1. +8 −2 ext/cmain.cpp
  2. +6 −1 ext/em.cpp
  3. +7 −1 ext/em.h
  4. +2 −1 ext/eventmachine.h
  5. +9 −2 ext/rubymain.cpp
  6. +15 −1 lib/eventmachine.rb
View
@@ -82,10 +82,10 @@ extern "C" void evma_release_library()
evma_run_machine
****************/
-extern "C" void evma_run_machine()
+extern "C" int evma_run_machine()
{
ensure_eventmachine("evma_run_machine");
- EventMachine->Run();
+ return EventMachine->Run();
}
@@ -836,3 +836,9 @@ extern "C" uint64_t evma_get_current_loop_time()
ensure_eventmachine("evma_get_current_loop_time");
return EventMachine->GetCurrentLoopTime();
}
+
+extern "C" void evma_set_one_shot_only(int val)
+{
+ ensure_eventmachine("evma_set_one_shot_only");
+ EventMachine->SetOneShotOnly(val == 1);
+}
View
@@ -73,6 +73,7 @@ EventMachine_t::EventMachine_t (EMCallback event_callback):
NextHeartbeatTime (0),
LoopBreakerReader (-1),
LoopBreakerWriter (-1),
+ OneShotOnly(false),
bTerminateSignalReceived (false),
bEpoll (false),
epfd (-1),
@@ -432,7 +433,7 @@ void EventMachine_t::ClearHeartbeat(uint64_t key, EventableDescriptor* ed)
EventMachine_t::Run
*******************/
-void EventMachine_t::Run()
+int EventMachine_t::Run()
{
#ifdef HAVE_EPOLL
if (bEpoll) {
@@ -487,7 +488,11 @@ void EventMachine_t::Run()
break;
if (bTerminateSignalReceived)
break;
+ if (OneShotOnly)
+ return 0;
}
+
+ return 1;
}
View
@@ -65,7 +65,7 @@ class EventMachine_t
EventMachine_t (EMCallback);
virtual ~EventMachine_t();
- void Run();
+ int Run();
void ScheduleHalt();
void SignalLoopBreaker();
const unsigned long InstallOneshotTimer (int);
@@ -130,6 +130,10 @@ class EventMachine_t
uint64_t GetRealTime();
+ bool SetOneShotOnly(bool val) {
+ OneShotOnly = val;
+ }
+
private:
bool _RunOnce();
bool _RunTimers();
@@ -188,6 +192,8 @@ class EventMachine_t
unsigned LastTickCount;
#endif
+ bool OneShotOnly;
+
private:
bool bTerminateSignalReceived;
View
@@ -41,7 +41,7 @@ extern "C" {
};
void evma_initialize_library (EMCallback);
- void evma_run_machine();
+ int evma_run_machine();
void evma_release_library();
const unsigned long evma_install_oneshot_timer (int seconds);
const unsigned long evma_connect_to_server (const char *bind_addr, int bind_port, const char *server, int port);
@@ -114,6 +114,7 @@ extern "C" {
void evma_set_kqueue (int use);
uint64_t evma_get_current_loop_time();
+ void evma_set_one_shot_only(int val);
#if __cplusplus
}
#endif
View
@@ -220,8 +220,7 @@ t_run_machine_without_threads
static VALUE t_run_machine_without_threads (VALUE self)
{
- evma_run_machine();
- return Qnil;
+ return evma_run_machine() ? Qtrue : Qfalse;
}
@@ -917,6 +916,12 @@ static VALUE t__kqueue_set (VALUE self, VALUE val)
return val;
}
+static VALUE t_set_one_shot_only (VALUE self, VALUE val)
+{
+ evma_set_one_shot_only(RTEST(val));
+ return val;
+}
+
/********
t__ssl_p
@@ -1187,6 +1192,8 @@ extern "C" void Init_rubyeventmachine()
rb_define_module_function (EmModule, "kqueue=", (VALUE(*)(...))t__kqueue_set, 1);
rb_define_module_function (EmModule, "kqueue?", (VALUE(*)(...))t__kqueue_p, 0);
+ rb_define_module_function (EmModule, "one_shot_only=", (VALUE(*)(...))t_set_one_shot_only, 1);
+
rb_define_module_function (EmModule, "ssl?", (VALUE(*)(...))t__ssl_p, 0);
rb_define_method (EmConnection, "get_outbound_data_size", (VALUE(*)(...))conn_get_outbound_data_size, 0);
View
@@ -198,12 +198,26 @@ def self.run blk=nil, tail=nil, &block
begin
@reactor_running = true
initialize_event_machine
+
+ # Only have +run_machine+ crank once and then return.
+ # This allows rubinius to deal with the objects accessed
+ # by +run_machine+ properly as garbage.
+ if defined?(RUBY_ENGINE) and RUBY_ENGINE == "rbx"
+ self.one_shot_only = true
+ end
+
(b = blk || block) and add_timer(0, b)
if @next_tick_queue && !@next_tick_queue.empty?
add_timer(0) { signal_loopbreak }
end
@reactor_thread = Thread.current
- run_machine
+
+ # Crank the machine in a loop. +run_machine+ returns
+ # true if there is a legit reason to exit the loop, otherwise
+ # we just keep running it.
+ while true
+ break if run_machine
+ end
ensure
until @tails.empty?
@tails.pop.call

0 comments on commit 72e9fc2

Please sign in to comment.