Open mrbrdo opened 9 years ago
RSpec isn't entirely thread safe but it is something we're working towards, 3.x contains improvements towards thread safe mocks (in particular fixing a deadlock issue) but those fixes won't be back ported to 2.99 (as we're not maintaining 2.x). Can you try this on 3.x and reopen if it reoccurs?
I'm still getting the error on 3.x, this is how I stubbed:
allow_any_instance_of(SomeClass).to receive(:mobile?) { false }
Backtrace:
gems/rspec-mocks-3.4.1/lib/rspec/mocks/order_group.rb:17:in `<<': Detected invalid array contents due to unsynchronized modifications with concurrent users (ConcurrencyError)
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/order_group.rb:17:in `invoked'
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/proxy.rb:163:in `record_message_received'
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/proxy.rb:169:in `message_received'
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/proxy.rb:321:in `message_received'
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/method_double.rb:77:in `proxy_method_invoked'
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/method_double.rb:64:in `mobile?'
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/any_instance/recorder.rb:236:in `mobile?'
Another similar backtrace from another case:
gems/rspec-mocks-3.4.1/lib/rspec/mocks/order_group.rb:17:in `<<': Detected invalid array contents due to unsynchronized modifications with concurrent users (ConcurrencyError)
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/order_group.rb:17:in `invoked'
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/proxy.rb:163:in `record_message_received'
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/proxy.rb:169:in `message_received'
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/proxy.rb:321:in `message_received'
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/method_double.rb:77:in `proxy_method_invoked'
from gems/rspec-mocks-3.4.1/lib/rspec/mocks/method_double.rb:64:in `new'
I can't reopen this issue myself it seems.
Reopened.
@mrbrdo could you provide us a full spec file with a sample class and sample spec that produces this problem? I tried to reproduce this locally and couldn't.
Here is a self-contained example that consistently triggers on my machine:
# encoding: utf-8
require 'rspec'
require 'rspec/mocks'
require 'thread'
describe 'rspec-mocks validation thread-safety' do
it 'validates receive counts' do
parallelism = 10
repetition = 10
foo = double('Foo').as_null_object
# set an expectation
expect(foo).to receive(:bar).exactly(parallelism * repetition).times
# fulfil that expectation with some parallelism
parallelism.times.map do |outer_idx|
Thread.new do
repetition.times do |inner_idx|
foo.bar
end
end
end.map(&:join)
end
end
Result:
╭─{ yaauie@castrovel:~/src/scratch/rspec-thread-safety } ╰─● rspec spec/threadsafety_spec.rb rspec-mocks validation thread-safety validates receive counts (FAILED - 1) Failures: 1) rspec-mocks validation thread-safety validates receive counts Failure/Error: foo.bar ConcurrencyError: Detected invalid array contents due to unsynchronized modifications with concurrent users # ./spec/threadsafety_spec.rb:21:in `block in (root)' # ./spec/threadsafety_spec.rb:20:in `block in (root)' Finished in 0.08449 seconds (files took 0.69396 seconds to load) 1 example, 1 failure Failed examples: rspec ./spec/threadsafety_spec.rb:8 # rspec-mocks validation thread-safety validates receive counts rspec spec/threadsafety_spec.rb 12.25s user 0.43s system 381% cpu 3.320 total [error: 1]
RSpec and Plugin Versions:
╭─{ yaauie@castrovel:~/src/scratch/rspec-thread-safety } ╰─● rspec --version RSpec 3.8 - rspec-core 3.8.0 - rspec-expectations 3.8.1 - rspec-mocks 3.8.0 - rspec-support 3.8.0 rspec --version 9.73s user 0.40s system 341% cpu 2.969 total [success] ╭─{ yaauie@castrovel:~/src/scratch/rspec-thread-safety } ╰─● ruby --version jruby 9.1.12.0 (2.3.3) 2017-06-15 33c6439 Java HotSpot(TM) 64-Bit Server VM 25.152-b16 on 1.8.0_152-b16 +jit [darwin-x86_64] [success]
What's the status of this issue?
No change
I think there might be a thread-safety issue with stub_chain.
I am occasionally getting this error:
I am testing code that is threaded (JRuby). The tests themselves are not threaded (i.e. not using something like parallel_tests).
The method being called which produced this error was stubbed in this way:
The issue doesn't occur very often and so is hard to reproduce for me.
Thanks