From 625a2d642f68c00fa5db3f881dc3c6fcf818cd33 Mon Sep 17 00:00:00 2001 From: Will Fleming Date: Sun, 3 Jan 2016 17:21:54 -0500 Subject: [PATCH] Address FileThreadPool race condition I saw a couple ThreadErrors around popping from an empty queue in bugsnag: this got introduced when I moved away from catching all ThreadErrors. There's a race condition between checking that the queue is empty & attempting to pop from it. This change locks the pop operation with a mutex to prevent the race. --- lib/cc/engine/analyzers/file_thread_pool.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/lib/cc/engine/analyzers/file_thread_pool.rb b/lib/cc/engine/analyzers/file_thread_pool.rb index 971df120..33a4c531 100644 --- a/lib/cc/engine/analyzers/file_thread_pool.rb +++ b/lib/cc/engine/analyzers/file_thread_pool.rb @@ -14,10 +14,11 @@ def initialize(files, concurrency: DEFAULT_CONCURRENCY) def run(&block) queue = build_queue + lock = Mutex.new @workers = thread_count.times.map do Thread.new do - while !queue.empty? && (item = queue.pop(true)) + while (item = next_item(queue, lock)) yield item end end @@ -32,6 +33,10 @@ def join attr_reader :files, :concurrency, :workers + def next_item(queue, lock) + lock.synchronize { queue.pop(true) unless queue.empty? } + end + def build_queue Queue.new.tap do |queue| files.each do |file|