aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/main/java/com/google/devtools/build/lib/standalone
diff options
context:
space:
mode:
authorGravatar ulfjack <ulfjack@google.com>2017-06-16 15:25:42 +0200
committerGravatar Philipp Wollermann <philwo@google.com>2017-06-19 18:23:00 +0200
commitacd291a520d392977a2efff17949b75c2fa80eef (patch)
treea3da9f3eda8844425cdbb28d291eedee400c8069 /src/main/java/com/google/devtools/build/lib/standalone
parent560bcb8653947d5d38fa9710c25b7eff6596b2fc (diff)
Rewrite StandaloneSpawnStrategy to use LocalSpawnRunner
PiperOrigin-RevId: 159221067
Diffstat (limited to 'src/main/java/com/google/devtools/build/lib/standalone')
-rw-r--r--src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java52
-rw-r--r--src/main/java/com/google/devtools/build/lib/standalone/StandaloneModule.java2
-rw-r--r--src/main/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategy.java179
3 files changed, 116 insertions, 117 deletions
diff --git a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java
index 12e508dbe0..c1dbbac6f5 100644
--- a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java
+++ b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneActionContextProvider.java
@@ -13,20 +13,23 @@
// limitations under the License.
package com.google.devtools.build.lib.standalone;
+import com.google.common.base.Preconditions;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableList.Builder;
import com.google.devtools.build.lib.actions.Action;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
+import com.google.devtools.build.lib.actions.ActionInputFileCache;
import com.google.devtools.build.lib.actions.Artifact;
import com.google.devtools.build.lib.actions.ArtifactResolver;
import com.google.devtools.build.lib.actions.ExecutionStrategy;
import com.google.devtools.build.lib.actions.Executor.ActionContext;
-import com.google.devtools.build.lib.buildtool.BuildRequest;
+import com.google.devtools.build.lib.actions.ResourceManager;
import com.google.devtools.build.lib.exec.ActionContextProvider;
+import com.google.devtools.build.lib.exec.ActionInputPrefetcher;
import com.google.devtools.build.lib.exec.ExecutionOptions;
import com.google.devtools.build.lib.exec.FileWriteStrategy;
import com.google.devtools.build.lib.exec.StandaloneTestStrategy;
import com.google.devtools.build.lib.exec.TestStrategy;
+import com.google.devtools.build.lib.exec.local.LocalExecutionOptions;
import com.google.devtools.build.lib.rules.cpp.IncludeScanningContext;
import com.google.devtools.build.lib.rules.cpp.SpawnGccStrategy;
import com.google.devtools.build.lib.rules.test.ExclusiveTestStrategy;
@@ -64,39 +67,46 @@ public class StandaloneActionContextProvider extends ActionContextProvider {
}
private final CommandEnvironment env;
- private final ImmutableList<ActionContext> strategies;
+ private ActionInputPrefetcher actionInputPrefetcher;
- public StandaloneActionContextProvider(CommandEnvironment env, BuildRequest buildRequest) {
+ public StandaloneActionContextProvider(CommandEnvironment env) {
this.env = env;
- ExecutionOptions options = buildRequest.getOptions(ExecutionOptions.class);
- boolean verboseFailures = options.verboseFailures;
+ }
- Path testTmpRoot = TestStrategy.getTmpRoot(env.getWorkspace(), env.getExecRoot(), options);
- TestActionContext testStrategy =
- new StandaloneTestStrategy(
- buildRequest, env.getBlazeWorkspace().getBinTools(), testTmpRoot);
+ @Override
+ public void init(
+ ActionInputFileCache actionInputFileCache, ActionInputPrefetcher actionInputPrefetcher) {
+ this.actionInputPrefetcher = Preconditions.checkNotNull(actionInputPrefetcher);
+ }
- Builder<ActionContext> strategiesBuilder = ImmutableList.builder();
+ @Override
+ public Iterable<? extends ActionContext> getActionContexts() {
+ ExecutionOptions executionOptions = env.getOptions().getOptions(ExecutionOptions.class);
+ LocalExecutionOptions localExecutionOptions =
+ env.getOptions().getOptions(LocalExecutionOptions.class);
+ Path testTmpRoot =
+ TestStrategy.getTmpRoot(env.getWorkspace(), env.getExecRoot(), executionOptions);
+ TestActionContext testStrategy =
+ new StandaloneTestStrategy(
+ executionOptions,
+ env.getBlazeWorkspace().getBinTools(),
+ testTmpRoot);
// Order of strategies passed to builder is significant - when there are many strategies that
// could potentially be used and a spawnActionContext doesn't specify which one it wants, the
// last one from strategies list will be used
- strategiesBuilder.add(
+ return ImmutableList.of(
new StandaloneSpawnStrategy(
env.getExecRoot(),
- verboseFailures,
- env.getRuntime().getProductName()),
+ actionInputPrefetcher,
+ localExecutionOptions,
+ executionOptions.verboseFailures,
+ env.getRuntime().getProductName(),
+ ResourceManager.instance()),
new DummyIncludeScanningContext(),
new SpawnGccStrategy(),
testStrategy,
new ExclusiveTestStrategy(testStrategy),
new FileWriteStrategy());
-
- this.strategies = strategiesBuilder.build();
- }
-
- @Override
- public Iterable<ActionContext> getActionContexts() {
- return strategies;
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneModule.java b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneModule.java
index b60f47aa1e..6f299fa616 100644
--- a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneModule.java
+++ b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneModule.java
@@ -24,7 +24,7 @@ import com.google.devtools.build.lib.runtime.CommandEnvironment;
public class StandaloneModule extends BlazeModule {
@Override
public void executorInit(CommandEnvironment env, BuildRequest request, ExecutorBuilder builder) {
- builder.addActionContextProvider(new StandaloneActionContextProvider(env, request));
+ builder.addActionContextProvider(new StandaloneActionContextProvider(env));
builder.addActionContextConsumer(new StandaloneActionContextConsumer());
}
}
diff --git a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategy.java b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategy.java
index 724542ff1b..de47fe42d2 100644
--- a/src/main/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategy.java
+++ b/src/main/java/com/google/devtools/build/lib/standalone/StandaloneSpawnStrategy.java
@@ -15,32 +15,36 @@ package com.google.devtools.build.lib.standalone;
import com.google.common.eventbus.EventBus;
import com.google.devtools.build.lib.actions.ActionExecutionContext;
-import com.google.devtools.build.lib.actions.ActionExecutionMetadata;
+import com.google.devtools.build.lib.actions.ActionInput;
+import com.google.devtools.build.lib.actions.ActionInputFileCache;
import com.google.devtools.build.lib.actions.ActionStatusMessage;
import com.google.devtools.build.lib.actions.ExecException;
import com.google.devtools.build.lib.actions.ExecutionStrategy;
import com.google.devtools.build.lib.actions.Executor;
import com.google.devtools.build.lib.actions.ResourceManager;
-import com.google.devtools.build.lib.actions.ResourceManager.ResourceHandle;
import com.google.devtools.build.lib.actions.Spawn;
import com.google.devtools.build.lib.actions.SpawnActionContext;
import com.google.devtools.build.lib.actions.Spawns;
import com.google.devtools.build.lib.actions.UserExecException;
+import com.google.devtools.build.lib.exec.ActionInputPrefetcher;
+import com.google.devtools.build.lib.exec.SpawnExecException;
+import com.google.devtools.build.lib.exec.SpawnInputExpander;
+import com.google.devtools.build.lib.exec.SpawnResult;
+import com.google.devtools.build.lib.exec.SpawnResult.Status;
+import com.google.devtools.build.lib.exec.SpawnRunner.ProgressStatus;
+import com.google.devtools.build.lib.exec.SpawnRunner.SpawnExecutionPolicy;
import com.google.devtools.build.lib.exec.apple.XCodeLocalEnvProvider;
import com.google.devtools.build.lib.exec.local.LocalEnvProvider;
-import com.google.devtools.build.lib.shell.AbnormalTerminationException;
-import com.google.devtools.build.lib.shell.Command;
-import com.google.devtools.build.lib.shell.CommandException;
-import com.google.devtools.build.lib.shell.TerminationStatus;
+import com.google.devtools.build.lib.exec.local.LocalExecutionOptions;
+import com.google.devtools.build.lib.exec.local.LocalSpawnRunner;
+import com.google.devtools.build.lib.rules.fileset.FilesetActionContext;
import com.google.devtools.build.lib.util.CommandFailureUtils;
import com.google.devtools.build.lib.util.OS;
-import com.google.devtools.build.lib.util.OsUtils;
import com.google.devtools.build.lib.util.io.FileOutErr;
import com.google.devtools.build.lib.vfs.Path;
-import java.io.File;
+import com.google.devtools.build.lib.vfs.PathFragment;
import java.io.IOException;
-import java.util.ArrayList;
-import java.util.List;
+import java.util.SortedMap;
/**
* Strategy that uses subprocessing to execute a process.
@@ -48,112 +52,97 @@ import java.util.List;
@ExecutionStrategy(name = { "standalone", "local" }, contextType = SpawnActionContext.class)
public class StandaloneSpawnStrategy implements SpawnActionContext {
private final boolean verboseFailures;
- private final Path processWrapper;
- private final Path execRoot;
- private final String productName;
- private final ResourceManager resourceManager;
- private final LocalEnvProvider localEnvProvider;
-
- public StandaloneSpawnStrategy(Path execRoot, boolean verboseFailures, String productName) {
- this(execRoot, verboseFailures, productName, ResourceManager.instance());
- }
+ private final LocalSpawnRunner localSpawnRunner;
public StandaloneSpawnStrategy(
- Path execRoot, boolean verboseFailures, String productName, ResourceManager resourceManager) {
+ Path execRoot, ActionInputPrefetcher actionInputPrefetcher,
+ LocalExecutionOptions localExecutionOptions, boolean verboseFailures, String productName,
+ ResourceManager resourceManager) {
this.verboseFailures = verboseFailures;
- this.execRoot = execRoot;
- this.processWrapper = execRoot.getRelative(
- "_bin/process-wrapper" + OsUtils.executableExtension());
- this.productName = productName;
- this.resourceManager = resourceManager;
- this.localEnvProvider = OS.getCurrent() == OS.DARWIN
+ LocalEnvProvider localEnvProvider = OS.getCurrent() == OS.DARWIN
? new XCodeLocalEnvProvider()
: LocalEnvProvider.UNMODIFIED;
+ this.localSpawnRunner = new LocalSpawnRunner(
+ execRoot,
+ actionInputPrefetcher,
+ localExecutionOptions,
+ resourceManager,
+ productName,
+ localEnvProvider);
}
/**
* Executes the given {@code spawn}.
*/
@Override
- public void exec(Spawn spawn,
- ActionExecutionContext actionExecutionContext)
+ public void exec(final Spawn spawn, final ActionExecutionContext actionExecutionContext)
throws ExecException, InterruptedException {
- EventBus eventBus = actionExecutionContext.getExecutor().getEventBus();
- ActionExecutionMetadata owner = spawn.getResourceOwner();
- eventBus.post(ActionStatusMessage.schedulingStrategy(owner));
- try (ResourceHandle handle =
- resourceManager.acquireResources(owner, spawn.getLocalResources())) {
- eventBus.post(ActionStatusMessage.runningStrategy(owner, "standalone"));
- try {
- actuallyExec(spawn, actionExecutionContext);
- } catch (IOException e) {
- throw new UserExecException("I/O exception during local execution", e);
+ final int timeoutSeconds = Spawns.getTimeoutSeconds(spawn);
+ final EventBus eventBus = actionExecutionContext.getExecutor().getEventBus();
+ SpawnExecutionPolicy policy = new SpawnExecutionPolicy() {
+ @Override
+ public ActionInputFileCache getActionInputFileCache() {
+ return actionExecutionContext.getActionInputFileCache();
}
- }
- }
- /**
- * Executes the given {@code spawn}.
- */
- private void actuallyExec(Spawn spawn,
- ActionExecutionContext actionExecutionContext)
- throws ExecException, IOException {
- Executor executor = actionExecutionContext.getExecutor();
+ @Override
+ public void lockOutputFiles() throws InterruptedException {
+ // Do nothing for now.
+ }
- if (executor.reportsSubcommands()) {
- executor.reportSubcommand(spawn);
- }
+ @Override
+ public long getTimeoutMillis() {
+ return timeoutSeconds * 1000L;
+ }
- int timeoutSeconds = Spawns.getTimeoutSeconds(spawn);
+ @Override
+ public FileOutErr getFileOutErr() {
+ return actionExecutionContext.getFileOutErr();
+ }
- // We must wrap the subprocess with process-wrapper to kill the process tree.
- // All actions therefore depend on the process-wrapper file. Since it's embedded,
- // we don't bother with declaring it as an input.
- List<String> args = new ArrayList<>();
- if (OS.getCurrent() != OS.WINDOWS) {
- // TODO(bazel-team): process-wrapper seems to work on Windows, but requires
- // additional setup as it is an msys2 binary, so it needs msys2 DLLs on %PATH%.
- // Disable it for now to make the setup easier and to avoid further PATH hacks.
- // Ideally we should have a native implementation of process-wrapper for Windows.
- args.add(processWrapper.getPathString());
- args.add(Integer.toString(timeoutSeconds));
- args.add("5"); /* kill delay: give some time to print stacktraces and whatnot. */
+ @Override
+ public SortedMap<PathFragment, ActionInput> getInputMapping() throws IOException {
+ return new SpawnInputExpander(/*strict*/false)
+ .getInputMapping(
+ spawn,
+ actionExecutionContext.getArtifactExpander(),
+ actionExecutionContext.getActionInputFileCache(),
+ actionExecutionContext.getExecutor().getContext(FilesetActionContext.class));
+ }
- // TODO(bazel-team): use process-wrapper redirection so we don't have to
- // pass test logs through the Java heap.
- args.add("-"); /* stdout. */
- args.add("-"); /* stderr. */
- }
- args.addAll(spawn.getArguments());
+ @Override
+ public void report(ProgressStatus state) {
+ switch (state) {
+ case EXECUTING:
+ String strategyName = "local";
+ eventBus.post(
+ ActionStatusMessage.runningStrategy(spawn.getResourceOwner(), strategyName));
+ break;
+ case SCHEDULING:
+ eventBus.post(ActionStatusMessage.schedulingStrategy(spawn.getResourceOwner()));
+ break;
+ default:
+ break;
+ }
+ }
+ };
- String cwd = executor.getExecRoot().getPathString();
- Command cmd =
- new Command(
- args.toArray(new String[] {}),
- localEnvProvider.rewriteLocalEnv(spawn.getEnvironment(), execRoot, productName),
- new File(cwd),
- OS.getCurrent() == OS.WINDOWS && timeoutSeconds >= 0 ? timeoutSeconds * 1000 : -1);
+ Executor executor = actionExecutionContext.getExecutor();
+ if (executor.reportsSubcommands()) {
+ executor.reportSubcommand(spawn);
+ }
- FileOutErr outErr = actionExecutionContext.getFileOutErr();
try {
- cmd.execute(
- /* stdin */ new byte[] {},
- Command.NO_OBSERVER,
- outErr.getOutputStream(),
- outErr.getErrorStream(),
- /*killSubprocessOnInterrupt*/ true);
- } catch (AbnormalTerminationException e) {
- TerminationStatus status = e.getResult().getTerminationStatus();
- boolean timedOut = !status.exited() && (
- status.timedout() || status.getTerminatingSignal() == 14 /* SIGALRM */);
- String message =
- CommandFailureUtils.describeCommandFailure(
- verboseFailures, spawn.getArguments(), spawn.getEnvironment(), cwd);
- throw new UserExecException(String.format("%s: %s", message, e), timedOut);
- } catch (CommandException e) {
- String message = CommandFailureUtils.describeCommandFailure(
- verboseFailures, spawn.getArguments(), spawn.getEnvironment(), cwd);
- throw new UserExecException(message, e);
+ SpawnResult result = localSpawnRunner.exec(spawn, policy);
+ if (result.status() != Status.SUCCESS || result.exitCode() != 0) {
+ String message =
+ CommandFailureUtils.describeCommandFailure(
+ verboseFailures, spawn.getArguments(), spawn.getEnvironment(), null);
+ throw new SpawnExecException(
+ message, result, /*forciblyRunRemotely=*/false, /*catastrophe=*/false);
+ }
+ } catch (IOException e) {
+ throw new UserExecException("I/O exception during local execution", e);
}
}