Fiber errors when using next_tick? #59

Closed
jtoy opened this Issue Sep 12, 2011 · 4 comments

Projects

None yet

3 participants

jtoy commented Sep 12, 2011

When I run the below code, it dies with a Fiber error, In my EM code I have lots of callbacks that run with timers and call themselves, how would I do this using em-synchrony?

/usr/local/lib/ruby/gems/1.9.1/gems/em-synchrony-1.0.0/lib/em-synchrony/em-redis.rb:42:in `yield': can't yield from root fiber (FiberError)

require "em-synchrony"
require "em-synchrony/em-redis"

EM.synchrony do
r = EM::Protocols::Redis.connect
i = 0

test = lambda {
puts i
r.rpush "afoo", "s1"
r.rpush "afoo", "s2"
i += 1
EM.next_tick &test
}

test.call
#EventMachine.stop

end

Contributor
lgierth commented Sep 13, 2011

You need to wrap the lambda's content in a Fiber.

test = lambda {
  Fiber.new {
    puts i
    r.rpush "afoo", "s1"
    r.rpush "afoo", "s2"
    i += 1
    EM.next_tick &test
  }.resume
}
jtoy commented Sep 13, 2011

That did the trick, why is the Fiber needed in this situation?

Contributor
lgierth commented Sep 13, 2011

I guess the EM-Redis driver does Fiber.yield when it waits for a response, which will give control back to the Fiber that resumed the one you're currently in. You're in the root Fiber because from the second call on, test will be called by EM.next_tick which isn't aware of Fibers.

I hope that didn't sound too scatterminded :)

Owner

Yep. EM.next tick schedules a ruby code block to run on the next tick. This block is then executed outside of the main fiber you were running in (hence it's in the root fiber), and hence the error you're seeing (can't yield from root fiber).

The solution above is exactly the fix, although we can probably provide a EM::Synchrony.next_tick to sugar coat the API.

@igrigorik igrigorik closed this in b6f90f5 Sep 30, 2011
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment