You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
# frozen_string_literal: truerequire"bundler/inline"gemfile(true)dosource"https://rubygems.org"gem"rails"gem"sqlite3","~> 1.4"endrequire"active_record"require"minitest/autorun"require"logger"# Have to use a persisted database rather than `:memory:`ActiveRecord::Base.establish_connection(adapter: "sqlite3",pool: 5,database: "deadlocker.sqlite3")ActiveRecord::Base.logger=Logger.new(STDOUT)ActiveRecord::Schema.definedocreate_table:posts,force: truedo |t|
endcreate_table:comments,force: truedo |t|
t.text:bodyendendclassComment < ActiveRecord::BaseendclassPost < ActiveRecord::Basebefore_save:deadlockdefdeadlockThread.newdo
::Comment.new(body: "deadlock_on_fetching_schema_cache_columns").save!end# Naively sleep for 1 second to give the thread a chance to start and fetch# the schema cache lock then block on the `LoadInterlockAwareMonitor`sleep(1)
::Comment.new(body: "deadlock_on_obtaining_schema_cache_lock").save!endendclassBugTest < Minitest::Testdeftest_deadlock# Mimic what happens in "full Rails" where we're running tests in a# transaction and the connection pool always uses the same connectionActiveRecord::Base.connection_pool.lock_thread=trueActiveRecord::Base.transactiondoputs"Attempting deadlock"Post.create!endendend
Expected behavior
I expect the test to pass and not deadlock.
Actual behavior
The main test thread has obtained the connection's LoadInterlockAwareMonitor lock in order to execute Post#save!. It's now the only thread allowed to execute SQL queries.
Another thread has been spawned that has obtained the Comment model's schema cache monitor lock in order to load the schema cache. This thread cannot execute the query to obtain the table's columns and blocks:
The main thread meanwhile now requires access to Comment and also attempts to load the schema cache. It cannot obtain the schema cache monitor lock and blocks:
Steps to reproduce
Expected behavior
I expect the test to pass and not deadlock.
Actual behavior
The main test thread has obtained the connection's
LoadInterlockAwareMonitor
lock in order to executePost#save!
. It's now the only thread allowed to execute SQL queries.Another thread has been spawned that has obtained the
Comment
model's schema cache monitor lock in order to load the schema cache. This thread cannot execute the query to obtain the table's columns and blocks:rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
Line 1000 in 747a03b
The main thread meanwhile now requires access to
Comment
and also attempts to load the schema cache. It cannot obtain the schema cache monitor lock and blocks:rails/activerecord/lib/active_record/model_schema.rb
Line 560 in 747a03b
System configuration
Rails version: 7.1.3.3
Ruby version: 3.2.2
The text was updated successfully, but these errors were encountered: