| // Copyright 2019 The Bazel Authors. All rights reserved. |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| |
| package com.google.devtools.build.lib.sandbox; |
| |
| import com.google.common.base.Joiner; |
| import com.google.common.collect.ImmutableMap; |
| import com.google.common.collect.ImmutableSet; |
| import com.google.devtools.build.lib.actions.ActionInput; |
| import com.google.devtools.build.lib.actions.ForbiddenActionInputException; |
| import com.google.devtools.build.lib.actions.Spawn; |
| import com.google.devtools.build.lib.exec.local.LocalEnvProvider; |
| import com.google.devtools.build.lib.exec.local.WindowsLocalEnvProvider; |
| import com.google.devtools.build.lib.runtime.CommandEnvironment; |
| import com.google.devtools.build.lib.sandbox.SandboxHelpers.SandboxInputs; |
| import com.google.devtools.build.lib.vfs.Path; |
| import com.google.devtools.build.lib.vfs.PathFragment; |
| import java.io.IOException; |
| import java.time.Duration; |
| |
| /** Spawn runner that uses BuildXL Sandbox APIs to execute a local subprocess. */ |
| final class WindowsSandboxedSpawnRunner extends AbstractSandboxSpawnRunner { |
| |
| private final SandboxHelpers helpers; |
| private final Path execRoot; |
| private final PathFragment windowsSandbox; |
| private final LocalEnvProvider localEnvProvider; |
| private final Duration timeoutKillDelay; |
| |
| /** |
| * Creates a sandboxed spawn runner that uses the {@code windows-sandbox} tool. |
| * |
| * @param helpers common tools and state across all spawns during sandboxed execution |
| * @param cmdEnv the command environment to use |
| * @param timeoutKillDelay an additional grace period before killing timing out commands |
| * @param windowsSandboxPath path to windows-sandbox binary |
| */ |
| WindowsSandboxedSpawnRunner( |
| SandboxHelpers helpers, |
| CommandEnvironment cmdEnv, |
| Duration timeoutKillDelay, |
| PathFragment windowsSandboxPath) { |
| super(cmdEnv); |
| this.helpers = helpers; |
| this.execRoot = cmdEnv.getExecRoot(); |
| this.windowsSandbox = windowsSandboxPath; |
| this.timeoutKillDelay = timeoutKillDelay; |
| this.localEnvProvider = new WindowsLocalEnvProvider(cmdEnv.getClientEnv()); |
| } |
| |
| @Override |
| protected SandboxedSpawn prepareSpawn(Spawn spawn, SpawnExecutionContext context) |
| throws IOException, ForbiddenActionInputException, InterruptedException { |
| Path tmpDir = createActionTemp(execRoot); |
| Path commandTmpDir = tmpDir.getRelative("work"); |
| commandTmpDir.createDirectory(); |
| ImmutableMap<String, String> environment = |
| localEnvProvider.rewriteLocalEnv( |
| spawn.getEnvironment(), binTools, commandTmpDir.getPathString()); |
| |
| SandboxInputs readablePaths = |
| helpers.processInputFiles( |
| context.getInputMapping(PathFragment.EMPTY_FRAGMENT, /* willAccessRepeatedly= */ true), |
| execRoot); |
| |
| ImmutableSet.Builder<Path> writablePaths = ImmutableSet.builder(); |
| writablePaths.addAll(getWritableDirs(execRoot, environment)); |
| for (ActionInput output : spawn.getOutputFiles()) { |
| writablePaths.add(execRoot.getRelative(output.getExecPath())); |
| } |
| |
| Duration timeout = context.getTimeout(); |
| |
| if (!readablePaths.getSymlinks().isEmpty()) { |
| throw new IOException( |
| "Windows sandbox does not support unresolved symlinks yet (" |
| + Joiner.on(", ").join(readablePaths.getSymlinks().keySet()) |
| + ")"); |
| } |
| |
| WindowsSandboxUtil.CommandLineBuilder commandLineBuilder = |
| WindowsSandboxUtil.commandLineBuilder(windowsSandbox, spawn.getArguments()) |
| .setWritableFilesAndDirectories(writablePaths.build()) |
| .setReadableFilesAndDirectories(readablePaths.getFiles()) |
| .setInaccessiblePaths(getInaccessiblePaths()) |
| .setUseDebugMode(getSandboxOptions().sandboxDebug) |
| .setKillDelay(timeoutKillDelay); |
| |
| if (!timeout.isZero()) { |
| commandLineBuilder.setTimeout(timeout); |
| } |
| |
| return new WindowsSandboxedSpawn( |
| execRoot, environment, commandLineBuilder.build(), spawn.getMnemonic()); |
| } |
| |
| private static Path createActionTemp(Path execRoot) throws IOException { |
| return execRoot.getRelative( |
| java.nio.file.Files.createTempDirectory( |
| java.nio.file.Paths.get(execRoot.getPathString()), "windows-sandbox.") |
| .getFileName() |
| .toString()); |
| } |
| |
| @Override |
| public String getName() { |
| return "windows-sandbox"; |
| } |
| } |