From 111874d8b57ed8772981d46091eb02e2e81344de Mon Sep 17 00:00:00 2001 From: Adam Markowitz Date: Fri, 1 Sep 2017 12:31:47 -0700 Subject: [PATCH 1/3] resolve waiting counter problem if a thread is in the wait state, but transitions into a killed state the waiting counter will not be decremented leaving the pool to believe there is a thread available and waiting to complete work when that is not the case. Introduce a begin..ensure block so that any thread exception raised while in the wait state properly balances the waiting counter. --- lib/puma/thread_pool.rb | 7 +++++-- test/test_thread_pool.rb | 20 ++++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/lib/puma/thread_pool.rb b/lib/puma/thread_pool.rb index c0bbedb1..bb6a73c7 100644 --- a/lib/puma/thread_pool.rb +++ b/lib/puma/thread_pool.rb @@ -122,8 +122,11 @@ module Puma @out_of_band_pending = false end not_full.signal - not_empty.wait mutex - @waiting -= 1 + begin + not_empty.wait mutex + ensure + @waiting -= 1 + end end work = todo.shift diff --git a/test/test_thread_pool.rb b/test/test_thread_pool.rb index 697f5c46..ccc07ae0 100644 --- a/test/test_thread_pool.rb +++ b/test/test_thread_pool.rb @@ -266,4 +266,24 @@ class TestThreadPool < Minitest::Test assert_equal 2, rescued.length refute rescued.compact.any?(&:alive?) end + + def test_correct_waiting_count_for_killed_threads + pool = new_pool(1, 1) { |_| } + + pause + + # simulate our waiting worker thread getting killed for whatever reason + pool.instance_eval { @workers[0].kill } + + pause + + pool.reap + + pause + + pool << 0 + + pause + assert_equal 0, pool.backlog + end end From 7f095b4445eabe70e2f4ae806b30ce7e26a20402 Mon Sep 17 00:00:00 2001 From: "John W. Phillips" Date: Wed, 10 Jun 2020 23:24:34 +0000 Subject: [PATCH 2/3] Resolve waiting counter issue --- History.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/History.md b/History.md index 6f066bbd..72752d6d 100644 --- a/History.md +++ b/History.md @@ -1,3 +1,7 @@ +### Master +* Bugfixes + * Resolve issue with threadpool waiting counter decrement when thread is killed + ## 5.0.0 * Features From 7dfd9fba25c61d37e17be4bb7935fd38aff11793 Mon Sep 17 00:00:00 2001 From: "John W. Phillips" Date: Wed, 10 Jun 2020 23:25:24 +0000 Subject: [PATCH 3/3] Update syntax of unit test. --- test/test_thread_pool.rb | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/test/test_thread_pool.rb b/test/test_thread_pool.rb index ccc07ae0..0e6f7645 100644 --- a/test/test_thread_pool.rb +++ b/test/test_thread_pool.rb @@ -269,21 +269,16 @@ class TestThreadPool < Minitest::Test def test_correct_waiting_count_for_killed_threads pool = new_pool(1, 1) { |_| } - - pause + sleep 1 # simulate our waiting worker thread getting killed for whatever reason pool.instance_eval { @workers[0].kill } - - pause - + sleep 1 pool.reap - - pause + sleep 1 pool << 0 - - pause + sleep 1 assert_equal 0, pool.backlog end end