rails: Loading Interlock conflicts with explicit thread use

Existing code that spawns a new thread and then waits on its result, where that thread triggers an autoload, can cause a deadlock in the Interlock.

We have no programmatic evidence that such a pattern is safe. The fact it’s survived in the real world, however, suggests the cases we care about are in fact safe-in-practice. Generally, they’re safe because the original thread is waiting for the entire time the second thread is running – so the “only one thread can autoload” rule is still actually enforced.


There are two variants of this situation.

The first is where the spawned thread is just doing arbitrary work. We can detect this when it tries to autoload and notices it doesn’t hold the share lock. As it’s detectable, we can raise a descriptive error, and/or offer a :trust_me concurrency mode which allows it (again, on the basis that while we can’t prove it’s safe, if the code already existed [pre-interlock, it was just as unsafe… we just weren’t noticing] and was not causing weird bugs, there’s a reasonable chance it’s okay).

The second is where the spawned thread enters the executor. Specifically, this can come up if the spawned thread is processing requests through the application’s rack middleware stack – Capybara does this. In this case, because the callee is properly using the new APIs, I can see no way to detect that something’s amiss.


In both cases, it’s really the calling thread that’s at fault: an autoload-capable thread cannot wait on another autoload-capable thread without yielding the lock. The capability to do so is new, but the problem was already there.

About this issue

  • Original URL
  • State: closed
  • Created 8 years ago
  • Comments: 36 (23 by maintainers)

Commits related to this issue

Most upvoted comments

It’s on our radar. Everybody on the team is quite busy and there’s a back log. Thank you for your patience

Will open up a PR to add some upgrading docs to warn about this, and try and give some possible solutions

Yes. I was going to do a write up soon. We’ve discussed it and we think that we would still like to improve the situation, but it’s not a blocker for 5.0.0.

I just ran into this too and lost of couple of hours. I’d rather have const_missing throw an exception when run on not the main thread to make it clear that this usage is problematic.

I tried adding this myself but it looks like the real answer is using the new raw_state method added to interlock to see if the thread you’re currently on is one that it currently knows about.