From 63a4aa65ff8eb0498b7a75a820d766e282763d21 Mon Sep 17 00:00:00 2001
From: Jarek Radosz <jradosz@gmail.com>
Date: Mon, 27 Jan 2020 02:59:54 +0100
Subject: [PATCH] DEV: Ignore `ls` errors when clearing FileStore cache (#8780)
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

A race condition issue is possible when multiple thread/processes are calling this method.
`ls` prints out to stderr "cannot access '...': No such file or directory" if any of the files it's currently trying to list are being removed by the `xargs rm -rf` in an another process. That doesn't affect the result, but it did raise an error before this change.

Tested on a production instance where the original issue was observed.

Co-Authored-By: RĂ©gis Hanol <regis@hanol.fr>
---
 lib/file_store/base_store.rb | 15 ++++++++++++---
 1 file changed, 12 insertions(+), 3 deletions(-)

diff --git a/lib/file_store/base_store.rb b/lib/file_store/base_store.rb
index 47c61b60ebe..563970d0880 100644
--- a/lib/file_store/base_store.rb
+++ b/lib/file_store/base_store.rb
@@ -150,14 +150,23 @@ module FileStore
       dir = File.dirname(path)
       FileUtils.mkdir_p(dir) unless Dir.exist?(dir)
       FileUtils.cp(file.path, path)
-      # keep latest 500 files
+
+      # Keep latest 500 files
       processes = Open3.pipeline(
-        "ls -t #{CACHE_DIR}",
+        ["ls -t #{CACHE_DIR}", err: "/dev/null"],
         "tail -n +#{CACHE_MAXIMUM_SIZE + 1}",
         "awk '$0=\"#{CACHE_DIR}\"$0'",
         "xargs rm -f"
       )
-      raise "Error clearing old cache" if !processes.all?(&:success?)
+
+      ls = processes.shift
+
+      # Exit status `1` in `ls` occurs when e.g. "listing a directory
+      # in which entries are actively being removed or renamed".
+      # It's safe to ignore it here.
+      if ![0, 1].include?(ls.exitstatus) || !processes.all?(&:success?)
+        raise "Error clearing old cache"
+      end
     end
 
     private