From c1f1f427f5be8169b67953276d0f717b911427e2 Mon Sep 17 00:00:00 2001 From: Bryce Kwon Date: Sat, 31 Oct 2026 14:07:40 -0700 Subject: Open the lock files close-on-exec Each exec filter and snapshot compressor a fill runs inherited the slot's lock descriptor beside the stdout it writes into. An flock lasts until its last copy closes and nothing waits for a process a filter leaves behind, so a fill killed before its rename could leave the slot locked, and served stale or uncached, for as long as such a process lived. The scan holds its lock across no exec and opens the same way so that the two stay alike. --- tests/t0003-cache.sh | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) (limited to 'tests') diff --git a/tests/t0003-cache.sh b/tests/t0003-cache.sh index 7e92b05..945ac63 100755 --- a/tests/t0003-cache.sh +++ b/tests/t0003-cache.sh @@ -267,4 +267,31 @@ test_expect_success 'a slot stays locked while an exec filter runs' ' ! grep "Unable to publish" first.err ' +# An flock lasts until the last copy of its descriptor closes, so a filter +# may hold the slot's lock file only as the stdout it writes the page to. A +# stray copy would keep the slot locked for as long as the filter, or +# anything it leaves running, lives on. +test_expect_success PERL 'a filter holds the lock file only as its stdout' ' + rm -rf cache3 && mkdir cache3 && + write_script fd-filter "$PERL_PATH" <<-\EOF && + use POSIX qw(fstat); + 1 while ; + my @lock = stat $ENV{LOCK_FILE} or die "$!\n"; + my @fds = grep { + my @fd = fstat($_); + @fd && $fd[0] == $lock[0] && $fd[1] == $lock[1] + } 0 .. 255; + print "lock file on fd @fds.\n"; + EOF + { + echo "cache-size=1" && + sed "/^cache-size=/d" bigkeyrc && + echo "repo.readme=:file-1" && + echo "repo.about-filter=exec:$PWD/fd-filter" + } >fdrc && + LOCK_FILE="$PWD/cache3/00000000.lock" CGIT_CONFIG="$PWD/fdrc" \ + QUERY_STRING="url=bigpage/about/" cgit >fd.out && + grep -F "lock file on fd 1." fd.out +' + test_done -- cgit