From 3ca4fd45c68a5e74f668c2ae212842b0e6036b18 Mon Sep 17 00:00:00 2001 From: oquenchil <23365806+oquenchil@users.noreply.github.com> Date: Tue, 27 Feb 2024 19:56:17 +0100 Subject: [PATCH] [7.1.0] Fix stale trash dir not cleaned up on worker creation (#21510) Cherrypicks: e482e8b The bug in Bazel is that ${output_base}/blaze-workers/_moved_trash_dir/ doesn't get wiped between blaze restarts. The directory to move to for asynchronous deletion is an incrementing AtomicInteger but after a restart it will be zero again. If there were previous directories there, we might get an error trying to replace a non-empty directory while renaming. --- .../lib/sandbox/AsynchronousTreeDeleter.java | 4 +++ .../google/devtools/build/lib/worker/BUILD | 3 +- .../build/lib/worker/WorkerFactory.java | 10 +++++-- .../build/lib/worker/WorkerModule.java | 30 +++++++++++++++++-- .../build/lib/worker/WorkerModuleTest.java | 27 +++++++++++++++++ 5 files changed, 67 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/AsynchronousTreeDeleter.java b/src/main/java/com/google/devtools/build/lib/sandbox/AsynchronousTreeDeleter.java index 70aa26583f5a16..ce809f3ad6c9d4 100644 --- a/src/main/java/com/google/devtools/build/lib/sandbox/AsynchronousTreeDeleter.java +++ b/src/main/java/com/google/devtools/build/lib/sandbox/AsynchronousTreeDeleter.java @@ -110,4 +110,8 @@ public void shutdown() { service = null; } } + + public Path getTrashBase() { + return trashBase; + } } diff --git a/src/main/java/com/google/devtools/build/lib/worker/BUILD b/src/main/java/com/google/devtools/build/lib/worker/BUILD index 9f0d8dc6b42835..03a625a5cc160c 100644 --- a/src/main/java/com/google/devtools/build/lib/worker/BUILD +++ b/src/main/java/com/google/devtools/build/lib/worker/BUILD @@ -102,7 +102,6 @@ java_library( "//src/main/java/com/google/devtools/build/lib/exec:execution_options", "//src/main/java/com/google/devtools/build/lib/exec:runfiles_tree_updater", "//src/main/java/com/google/devtools/build/lib/exec:spawn_strategy_registry", - "//src/main/java/com/google/devtools/build/lib/exec:tree_deleter", "//src/main/java/com/google/devtools/build/lib/exec/local", "//src/main/java/com/google/devtools/build/lib/runtime/commands/events", "//src/main/java/com/google/devtools/build/lib/sandbox:linux_sandbox_util", @@ -187,7 +186,7 @@ java_library( ":worker_events", ":worker_key", "//src/main/java/com/google/devtools/build/lib/events", - "//src/main/java/com/google/devtools/build/lib/exec:tree_deleter", + "//src/main/java/com/google/devtools/build/lib/sandbox:tree_deleter", "//src/main/java/com/google/devtools/build/lib/vfs", "//src/main/java/com/google/devtools/build/lib/vfs:pathfragment", "//third_party:apache_commons_pool2", diff --git a/src/main/java/com/google/devtools/build/lib/worker/WorkerFactory.java b/src/main/java/com/google/devtools/build/lib/worker/WorkerFactory.java index 6e1f6b33e594de..a47fbd834546c5 100644 --- a/src/main/java/com/google/devtools/build/lib/worker/WorkerFactory.java +++ b/src/main/java/com/google/devtools/build/lib/worker/WorkerFactory.java @@ -18,7 +18,7 @@ import com.google.common.io.BaseEncoding; import com.google.devtools.build.lib.events.Event; import com.google.devtools.build.lib.events.Reporter; -import com.google.devtools.build.lib.exec.TreeDeleter; +import com.google.devtools.build.lib.sandbox.AsynchronousTreeDeleter; import com.google.devtools.build.lib.vfs.Path; import com.google.devtools.build.lib.vfs.PathFragment; import com.google.devtools.build.lib.worker.SandboxedWorker.WorkerSandboxOptions; @@ -47,7 +47,7 @@ public class WorkerFactory extends BaseKeyedPooledObjectFactory module.workerPool.borrowObject(key)); } + @Test + public void buildStarting_cleansStaleTrashDirCleanedOnFirstBuild() throws Exception { + WorkerModule module = new WorkerModule(); + WorkerOptions options = WorkerOptions.DEFAULTS; + + when(request.getOptions(WorkerOptions.class)).thenReturn(options); + setupEnvironment("/outputRoot"); + + module.beforeCommand(env); + Path workerDir = fs.getPath("/outputRoot/outputBase/bazel-workers"); + Path trashBase = workerDir.getChild(AsynchronousTreeDeleter.MOVED_TRASH_DIR); + trashBase.createDirectoryAndParents(); + + Path staleTrash = trashBase.getChild("random-trash"); + + staleTrash.createDirectoryAndParents(); + module.buildStarting(BuildStartingEvent.create(env, request)); + // Trash is cleaned upon first build. + assertThat(staleTrash.exists()).isFalse(); + + staleTrash.createDirectoryAndParents(); + module.buildStarting(BuildStartingEvent.create(env, request)); + // Trash is not cleaned upon subsequent builds. + assertThat(staleTrash.exists()).isTrue(); + } + private void setupEnvironment(String rootDir) throws IOException, AbruptExitException { storedEventHandler = new StoredEventHandler(); Path root = fs.getPath(rootDir);