-
-
Save ahoward/c626ac69aea19a9f146aedaf314b7f9a to your computer and use it in GitHub Desktop.
rails just *cannot* run in threads. doing even simple things will bork it in strange and magical ways
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class B < A | |
B.dsl do | |
@state.push Thread.current | |
end | |
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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