From 2c3cff5422b115d7bb86ed28a056f3d368ebceeb Mon Sep 17 00:00:00 2001 From: larsrc Date: Thu, 17 Jun 2021 05:38:31 -0700 Subject: [PATCH] Check if `treeDeleter` is actually async before casting it. Fixes #13240. This code assumed that `registerSpawnStrategies` would be always be called before `afterCommand`, but that's not the case if the build was interrupted or failed before the execution phase. RELNOTES: None. PiperOrigin-RevId: 379937925 --- .../devtools/build/lib/sandbox/SandboxModule.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java b/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java index d64ebcdfe16165..4058f4bd5cd758 100644 --- a/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java +++ b/src/main/java/com/google/devtools/build/lib/sandbox/SandboxModule.java @@ -607,14 +607,17 @@ public void afterCommand() { SandboxOptions options = env.getOptions().getOptions(SandboxOptions.class); int asyncTreeDeleteThreads = options != null ? options.asyncTreeDeleteIdleThreads : 0; - if (treeDeleter != null && asyncTreeDeleteThreads > 0) { - // If asynchronous deletions were requested, they may still be ongoing so let them be: trying - // to delete the base tree synchronously could fail as we can race with those other deletions, - // and scheduling an asynchronous deletion could race with future builds. - AsynchronousTreeDeleter treeDeleter = - (AsynchronousTreeDeleter) checkNotNull(this.treeDeleter); + + // If asynchronous deletions were requested, they may still be ongoing so let them be: trying + // to delete the base tree synchronously could fail as we can race with those other deletions, + // and scheduling an asynchronous deletion could race with future builds. + if (asyncTreeDeleteThreads > 0 && treeDeleter instanceof AsynchronousTreeDeleter) { + AsynchronousTreeDeleter treeDeleter = (AsynchronousTreeDeleter) this.treeDeleter; treeDeleter.setThreads(asyncTreeDeleteThreads); } + // `treeDeleter` might not be an AsynchronousTreeDeleter if the user changed the option but + // then interrupted the build before the start of the execution phase. But that's OK, there + // will be nothing new to delete. See #13240. if (shouldCleanupSandboxBase) { try {