Forking after EventMachine reactor is running makes it disfunctional #213

Closed
michaelklishin opened this Issue May 31, 2011 · 3 comments

Comments

Projects
None yet
3 participants
Contributor

michaelklishin commented May 31, 2011

This is a reminder for a known problem: if EventMachine reactor is started before main process forks (a very common case with Unicorn and Passenger), EventMachine reactor becomes effectively disfunctional: EventMachine.reactor_running? returns true but no data is sent, EventMachine.stop has no effect and to completely reset reactor state one has to violate incapsulation by using Object#instance_variable_set.

Contributor

tmm1 commented May 31, 2011

We need to detect forks, possibly in EM.run if Process.pid has changed.

This usually causes problems using AMQP with forking http servers like unicorn and passenger. I initially wrote AMQP.fork as a workaround. Currently a hack is required:

     if EM.reactor_running?
       EM.stop_event_loop
       EM.release_machine
       EM.instance_variable_set('@reactor_running', false)
     end
Contributor

tmm1 commented Sep 10, 2011

This should work, can you verify?

diff --git a/lib/eventmachine.rb b/lib/eventmachine.rb
index 6e0fbf3..b2044e7 100644
--- a/lib/eventmachine.rb
+++ b/lib/eventmachine.rb
@@ -154,9 +154,15 @@ module EventMachine
     # which throws something inside of #run. Without the ensure, the second test
     # will start without release_machine being called and will immediately throw

-    #
-
+    if reactor_running? and @reactor_pid != Process.pid
+      # Reactor was started in a different parent, meaning we have forked.
+      # Clean up reactor state so a new reactor boots up in this child.
+      stop_event_loop
+      release_machine
+      @reactor_running = false
+    end

+    # Add tail call block
     tail and @tails.unshift(tail)

     if reactor_running?
@@ -169,6 +175,7 @@ module EventMachine
       @next_tick_queue ||= []
       @tails ||= []
       begin
+        @reactor_pid = Process.pid
         @reactor_running = true
         initialize_event_machine
         (b = blk || block) and add_timer(0, b)

tmm1 was assigned Sep 10, 2011

Contributor

michaelklishin commented Sep 10, 2011

Thank you, I will take a look in the next day or two.

raggi closed this in 427a76d Sep 29, 2011

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment