Bug #11071
closedStack consistency error while using RSpec and Timecop
Description
I have this Gemfile:
source 'https://rubygems.org'
ruby '2.2.2'
gem 'rspec'
gem 'timecop'
producing this Gemfile.lock:
GEM
remote: https://rubygems.org/
specs:
diff-lcs (1.2.5)
rspec (3.2.0)
rspec-core (~> 3.2.0)
rspec-expectations (~> 3.2.0)
rspec-mocks (~> 3.2.0)
rspec-core (3.2.3)
rspec-support (~> 3.2.0)
rspec-expectations (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-mocks (3.2.1)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.2.0)
rspec-support (3.2.2)
timecop (0.7.3)
PLATFORMS
ruby
DEPENDENCIES
rspec
timecop
and this test file:
# timecop_spec.rb
require 'timecop'
describe Timecop do
around do |example|
Timecop.travel(Time.parse('2015-01-01 06:30:00'), &example)
end
it 'sets the current time' do
Timecop.travel(Time.parse('2015-01-01 09:30:00')) {}
end
end
When I run bundle exec rspec -c timecop_spec.rb, this is the output:
/home/jcoglan/projects/futurelearn/timecop-segfault/.bundle/ruby/2.2.0/gems/timecop-0.7.3/lib/timecop/timecop.rb:142: [BUG] Stack consistency error (sp: 145, bp: 144)
ruby 2.2.2p95 (2015-04-13 revision 50295) [x86_64-linux]
Files
Updated by myronmarston (Myron Marston) over 10 years ago
There are two interesting things I've noticed about this:
- It does not happen on 2.1, so it appears to be a regression in 2.2.
- It appears to be related to
to_proc. If you change @jcoglan's example to use an around hook like this:
around do |example|
Timecop.travel(Time.parse('2015-01-01 06:30:00')) { example.run }
end
...the segfault does not happen. The to_proc definition is here, FWIW:
https://github.com/rspec/rspec-core/blob/v3.2.3/lib/rspec/core/example.rb#L244-L255
If some ruby core folks want to work on this and would like a more isolated example (e.g. an example that triggers the same bug w/o loading RSpec itself), let me know and I can try to pare it down to something more minimal.
Updated by nobu (Nobuyoshi Nakada) over 10 years ago
- Description updated (diff)
- File bug-11071.log bug-11071.log added
- Subject changed from Segfault while using RSpec and Timecop to Stack consistency error while using RSpec and Timecop
- Backport changed from 2.0.0: UNKNOWN, 2.1: UNKNOWN, 2.2: UNKNOWN to 2.0.0: DONTNEED, 2.1: DONTNEED, 2.2: REQUIRED
Reproduced with the trunk.
class E
def initialize(&proc)
@proc = proc
end
def run(a)
@proc.call
end
def to_proc
method(:run).to_proc
end
end
class T
def doit
yield nil
end
end
t = T.new
e = E.new {t.doit {}}
t.doit(&e)
Updated by nobu (Nobuyoshi Nakada) over 10 years ago
Possibly shortest code.
def doit
yield nil
end
doit(&proc {doit {}}.method(:call))
But it doesn't happen, if the inner block has a single argument or arbitrary number arguments *.
Oppositely, it's similar but sp is less than bp when the arguments are more than one.
And it seems the point to reenter the same method doit.
Updated by alexdowad (Alex Dowad) about 10 years ago
This is fixed by the patch I just posted for #11451.
Updated by usa (Usaku NAKAMURA) about 10 years ago
- Related to Bug #11451: MRI crashes with 'Stack inconsistency error' when a method which yields is called recursively in a particular way added
Updated by jeremyevans0 (Jeremy Evans) over 6 years ago
- Status changed from Open to Closed