From 6924f1ab15796f2e20b918fdf91c98d06f8c8369 Mon Sep 17 00:00:00 2001 From: Daniel Waterworth Date: Wed, 21 Aug 2019 14:47:44 +0100 Subject: [PATCH] FIX: Race-condition in fallback handlers (#8005) Calling `verify_master` in multiple threads simultaneously would cause multiple threads to be spawned. --- .../postgresql_fallback_adapter.rb | 22 ++++++++++--------- lib/discourse_redis.rb | 22 ++++++++++--------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/lib/active_record/connection_adapters/postgresql_fallback_adapter.rb b/lib/active_record/connection_adapters/postgresql_fallback_adapter.rb index 7094eb5053b..ce37de7c14e 100644 --- a/lib/active_record/connection_adapters/postgresql_fallback_adapter.rb +++ b/lib/active_record/connection_adapters/postgresql_fallback_adapter.rb @@ -32,19 +32,21 @@ class PostgreSQLFallbackHandler end def verify_master - synchronize { return if @thread && @thread.alive? } + synchronize do + return if @thread && @thread.alive? - @thread = Thread.new do - while true do - thread = Thread.new { initiate_fallback_to_master } - thread.abort_on_exception = true - thread.join - break if synchronize { @masters_down.hash.empty? } - sleep 5 + @thread = Thread.new do + while true do + thread = Thread.new { initiate_fallback_to_master } + thread.abort_on_exception = true + thread.join + break if synchronize { @masters_down.hash.empty? } + sleep 5 + end end - end - @thread.abort_on_exception = true + @thread.abort_on_exception = true + end end def master_down? diff --git a/lib/discourse_redis.rb b/lib/discourse_redis.rb index d62113d7519..e63ec530ab4 100644 --- a/lib/discourse_redis.rb +++ b/lib/discourse_redis.rb @@ -23,17 +23,19 @@ class DiscourseRedis end def verify_master - synchronize { return if @thread && @thread.alive? } + synchronize do + return if @thread && @thread.alive? - @thread = Thread.new do - loop do - begin - thread = Thread.new { initiate_fallback_to_master } - thread.join - break if synchronize { @master } - sleep 5 - ensure - thread.kill + @thread = Thread.new do + loop do + begin + thread = Thread.new { initiate_fallback_to_master } + thread.join + break if synchronize { @master } + sleep 5 + ensure + thread.kill + end end end end