Skip to content

Instantly share code, notes, and snippets.

@dnagir
Created June 25, 2014 04:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dnagir/80df45c96b49776dd174 to your computer and use it in GitHub Desktop.
Save dnagir/80df45c96b49776dd174 to your computer and use it in GitHub Desktop.
Unsafe Ruby vars
> ruby -v
ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-darwin13.0]
> ruby test.rb
Run options: --seed 22679
# Running:
F.
Finished in 2.320485s, 0.8619 runs/s, 172.3778 assertions/s.
1) Failure:
brute forcing#test_0001_breaks without synchronisation [tmp/test.rb:36]:
Expected: "1"
Actual: "84"
2 runs, 400 assertions, 1 failures, 0 errors, 0 skips
require 'minitest/autorun'
module Foo
class << self
attr_accessor :value
end
self.value = 'default'
end
def manipulate(new_value)
previous = Foo.value
begin
Foo.value = new_value
sleep 0.01 # pretend that we do something here, so that Foo.value may change
return Foo.value # which should be 'new_vaue' on MRI and God knows what elsewhere
ensure
Foo.value = previous
end
end
SYNC = Mutex.new
def safe_manipulate(new_value)
SYNC.synchronize { manipulate(new_value) }
end
describe "brute forcing" do
def run_test(&block)
threads = (1..200).map do |n1|
Thread.new do
assert_equal n1.to_s, block.call(n1.to_s)
end
end
threads.each(&:join)
end
it "breaks without synchronisation" do
run_test { |val| manipulate val }
end
it "works fine with synchronisation" do
run_test { |val| safe_manipulate val }
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment