concurrent-ruby
concurrent-ruby copied to clipboard
Promise.zip hangs on rejected promise in chain
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 withoutconcurrent-ruby-ext) - MRI 2.6.0 (fails at
n= 261) - JRuby 9.2.11.1 (fails at
nusually somewhere between 100-500) - TruffleRuby 20.0.0 (fails randomly with
[ruby] WARNING StackOverflowError, sometimes handlingn> 10000, other times failing atn= 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.