Skip to content

Instantly share code, notes, and snippets.

@ahoward ahoward/a.rb
Created Jan 31, 2019

Embed
What would you like to do?
rails just *cannot* run in threads. doing even simple things will bork it in strange and magical ways
class A
attr_accessor :dsl
attr_accessor :state
def initialize
@state = []
@dsl = self.class.dsl
sleep(rand)
instance_eval(&@dsl) if @dsl
sleep(rand)
end
def A.dsl(&block)
if block
@dsl = block
end
sleep(rand)
defined?(@dsl) && @dsl
end
end
class B < A
B.dsl do
@state.push Thread.current
end
end
threads =
[]
5.times do
threads <<
Thread.new do
Thread.current.abort_on_exception = true
(sleep(rand) && load('a.rb')) unless defined?(A) # initial rails autoload of base class
(sleep(rand) && load('b.rb')) unless defined?(B) # subsequent app load of a needed subclass of base
42.times do
b = B.new
raise 'borked' if b.state != [Thread.current]
end
end
end
threads.map{|t| t.join}
__END__
run this via and watch it bork:
~> while true;do ruby c.rb || say 'borked' && echo 'borked'; done
borked
borked
borked
borked
borked
borked
...
couple of notes:
- ruby's own require / load are NOT thread safe
- yet rails makes an attempt to implement an autoload that will be on top if it
- it ain't. well, it might be, but to find out you'd have to just write code
with 'A.foo' vs 'A.foo if defined?(A)', meaning you'd have to avoid all
'defined?' tests and trigger the `const_missing` handler rails uses to
attempt to work around mt loading issues. theoretically possible but
*extremely* fragile.
ref:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.