concurrent-ruby icon indicating copy to clipboard operation
concurrent-ruby copied to clipboard

Promise.zip hangs on rejected promise in chain

Open wjordan opened this issue 5 years ago • 0 comments

Promise.zip seems to hang with any rejected promise in its collection for large enough collections (several hundred items).

Here is a minimal repro:

1.upto(1000).map do |n|
  puts n
  promises = Array.new(n) do |i|
    Concurrent::Promise.new do
      raise 'rejected' if i.zero?
      '.'
    end
  end
  all = Concurrent::Promise.zip(*promises).execute
  all.wait(1)
  raise 'failed' if all.state == :unscheduled
end

Removing the rejected promise (e.g., removing the raise 'rejected' if i.zero? line) causes the code to run without issue for higher n as expected.

Tested on concurrent-ruby version 1.1.6, Ubuntu 18.04.4, with various rubies installed via rbenv:

  • MRI 2.7.1 (fails at n = 340 both with and without concurrent-ruby-ext)
  • MRI 2.6.0 (fails at n = 261)
  • JRuby 9.2.11.1 (fails at n usually somewhere between 100-500)
  • TruffleRuby 20.0.0 (fails randomly with [ruby] WARNING StackOverflowError, sometimes handling n > 10000, other times failing at n = 50)

Using the newer Promises APIs (e.g., replacing Concurrent::Promise.new with Concurrent::Promises.future and Concurrent::Promises.zip with Concurrent::Promises) seems to work without any issues for much higher n. This still seems like a valid bug for as long the original Promise APIs are still available and bugs are still being fixed in them.

wjordan avatar May 08 '20 17:05 wjordan