Commit f1c6772e authored by Mehmet Emin INAC's avatar Mehmet Emin INAC

Fix the race-condition issue on `IgnorableColumns`

Since the Ruby threads are preemptive on the user level, the scheduler
can decide to do the context switching to give the execution to another
thread after the conditional check. If this happens, two threads will
generate the exact same object. We can avoid this by just synchronizing
the whole block.

Since the `Mutex` is not `reentrant` in Ruby, I've also changed the way
we synchronize the critical section with `Monitor`.
parent 1928b708
...@@ -31,15 +31,13 @@ module IgnorableColumns ...@@ -31,15 +31,13 @@ module IgnorableColumns
alias_method :ignore_column, :ignore_columns alias_method :ignore_column, :ignore_columns
def ignored_columns_details def ignored_columns_details
unless defined?(@ignored_columns_details) return @ignored_columns_details if defined?(@ignored_columns_details)
IGNORE_COLUMN_MUTEX.synchronize do
@ignored_columns_details ||= superclass.try(:ignored_columns_details)&.dup || {}
end
end
@ignored_columns_details IGNORE_COLUMN_MONITOR.synchronize do
@ignored_columns_details ||= superclass.try(:ignored_columns_details)&.dup || {}
end
end end
IGNORE_COLUMN_MUTEX = Mutex.new IGNORE_COLUMN_MONITOR = Monitor.new
end end
end end
...@@ -59,6 +59,14 @@ RSpec.describe IgnorableColumns do ...@@ -59,6 +59,14 @@ RSpec.describe IgnorableColumns do
it_behaves_like 'storing removal information' it_behaves_like 'storing removal information'
end end
context 'when called on a subclass without setting the ignored columns' do
let(:subclass) { Class.new(record_class) }
it 'does not raise Deadlock error' do
expect { subclass.ignored_columns_details }.not_to raise_error
end
end
it 'defaults to empty Hash' do it 'defaults to empty Hash' do
expect(subject.ignored_columns_details).to eq({}) expect(subject.ignored_columns_details).to eq({})
end end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment