Search in sources :

Example 1 with UserExecException

use of com.google.devtools.build.lib.actions.UserExecException in project bazel by bazelbuild.

the class AppleHostInfo method getSdkRoot.

/**
   * Returns the absolute root path of the target Apple SDK on the host system for a given
   * version of xcode (as defined by the given {@code developerDir}). This may spawn a
   * process and use the {@code /usr/bin/xcrun} binary to locate the target SDK. This uses a local
   * cache file under {@code bazel-out}, and will only spawn a new {@code xcrun} process in the case
   * of a cache miss.
   *
   * @param execRoot the execution root path, used to locate the cache file
   * @param developerDir the value of {@code DEVELOPER_DIR} for the target version of xcode
   * @param sdkVersion the sdk version, for example, "9.1"
   * @param appleSdkPlatform the sdk platform, for example, "iPhoneOS"
   * @param productName the product name
   * @throws UserExecException if there is an issue with obtaining the root from the spawned
   *     process, either because the SDK platform/version pair doesn't exist, or there was an
   *     unexpected issue finding or running the tool
   */
public static String getSdkRoot(Path execRoot, String developerDir, String sdkVersion, String appleSdkPlatform, String productName) throws UserExecException {
    try {
        CacheManager cacheManager = new CacheManager(execRoot.getRelative(BlazeDirectories.getRelativeOutputPath(productName)), XCRUN_CACHE_FILENAME);
        String sdkString = appleSdkPlatform.toLowerCase() + sdkVersion;
        String cacheResult = cacheManager.getValue(developerDir, sdkString);
        if (cacheResult != null) {
            return cacheResult;
        } else {
            Map<String, String> env = Strings.isNullOrEmpty(developerDir) ? ImmutableMap.<String, String>of() : ImmutableMap.of("DEVELOPER_DIR", developerDir);
            CommandResult xcrunResult = new Command(new String[] { "/usr/bin/xcrun", "--sdk", sdkString, "--show-sdk-path" }, env, null).execute();
            // calling xcrun via Command returns a value with a newline on the end.
            String sdkRoot = new String(xcrunResult.getStdout(), StandardCharsets.UTF_8).trim();
            cacheManager.writeEntry(ImmutableList.of(developerDir, sdkString), sdkRoot);
            return sdkRoot;
        }
    } catch (AbnormalTerminationException e) {
        TerminationStatus terminationStatus = e.getResult().getTerminationStatus();
        if (terminationStatus.exited()) {
            throw new UserExecException(String.format("xcrun failed with code %s.\n" + "This most likely indicates that SDK version [%s] for platform [%s] is " + "unsupported for the target version of xcode.\n" + "%s\n" + "Stderr: %s", terminationStatus.getExitCode(), sdkVersion, appleSdkPlatform, terminationStatus.toString(), new String(e.getResult().getStderr(), StandardCharsets.UTF_8)));
        }
        String message = String.format("xcrun failed.\n%s\n%s", e.getResult().getTerminationStatus(), new String(e.getResult().getStderr(), StandardCharsets.UTF_8));
        throw new UserExecException(message, e);
    } catch (CommandException | IOException e) {
        throw new UserExecException(e);
    }
}
Also used : Command(com.google.devtools.build.lib.shell.Command) TerminationStatus(com.google.devtools.build.lib.shell.TerminationStatus) UserExecException(com.google.devtools.build.lib.actions.UserExecException) AbnormalTerminationException(com.google.devtools.build.lib.shell.AbnormalTerminationException) CommandException(com.google.devtools.build.lib.shell.CommandException) IOException(java.io.IOException) CommandResult(com.google.devtools.build.lib.shell.CommandResult)

Example 2 with UserExecException

use of com.google.devtools.build.lib.actions.UserExecException in project bazel by bazelbuild.

the class AppleHostInfo method getDeveloperDir.

/**
   * Returns the absolute root path of the xcode developer directory on the host system for
   * the given xcode version. This may spawn a process and use the {@code xcode-locator} binary.
   * This uses a local cache file under {@code bazel-out}, and will only spawn a new process in the
   * case of a cache miss.
   *
   * @param execRoot the execution root path, used to locate the cache file
   * @param version the xcode version number to look up
   * @param productName the product name
   * @throws UserExecException if there is an issue with obtaining the path from the spawned
   *     process, either because there is no installed xcode with the given version, or
   *     there was an unexpected issue finding or running the tool
   */
public static String getDeveloperDir(Path execRoot, DottedVersion version, String productName) throws UserExecException {
    try {
        CacheManager cacheManager = new CacheManager(execRoot.getRelative(BlazeDirectories.getRelativeOutputPath(productName)), XCODE_LOCATOR_CACHE_FILENAME);
        String cacheResult = cacheManager.getValue(version.toString());
        if (cacheResult != null) {
            return cacheResult;
        } else {
            CommandResult xcodeLocatorResult = new Command(new String[] { execRoot.getRelative("_bin/xcode-locator").getPathString(), version.toString() }).execute();
            String developerDir = new String(xcodeLocatorResult.getStdout(), StandardCharsets.UTF_8).trim();
            cacheManager.writeEntry(ImmutableList.of(version.toString()), developerDir);
            return developerDir;
        }
    } catch (AbnormalTerminationException e) {
        TerminationStatus terminationStatus = e.getResult().getTerminationStatus();
        String message;
        if (e.getResult().getTerminationStatus().exited()) {
            message = String.format("xcode-locator failed with code %s.\n" + "This most likely indicates that xcode version %s is not available on the host " + "machine.\n" + "%s\n" + "stderr: %s", terminationStatus.getExitCode(), version, terminationStatus.toString(), new String(e.getResult().getStderr(), StandardCharsets.UTF_8));
        } else {
            message = String.format("xcode-locator failed. %s\nstderr: %s", e.getResult().getTerminationStatus(), new String(e.getResult().getStderr(), StandardCharsets.UTF_8));
        }
        throw new UserExecException(message, e);
    } catch (CommandException | IOException e) {
        throw new UserExecException(e);
    }
}
Also used : Command(com.google.devtools.build.lib.shell.Command) TerminationStatus(com.google.devtools.build.lib.shell.TerminationStatus) UserExecException(com.google.devtools.build.lib.actions.UserExecException) AbnormalTerminationException(com.google.devtools.build.lib.shell.AbnormalTerminationException) CommandException(com.google.devtools.build.lib.shell.CommandException) IOException(java.io.IOException) CommandResult(com.google.devtools.build.lib.shell.CommandResult)

Example 3 with UserExecException

use of com.google.devtools.build.lib.actions.UserExecException in project bazel by bazelbuild.

the class DarwinSandboxedStrategy method actuallyExec.

private void actuallyExec(Spawn spawn, ActionExecutionContext actionExecutionContext, AtomicReference<Class<? extends SpawnActionContext>> writeOutputFiles) throws ExecException, InterruptedException {
    Executor executor = actionExecutionContext.getExecutor();
    SandboxHelpers.reportSubcommand(executor, spawn);
    PrintWriter errWriter = sandboxDebug ? new PrintWriter(actionExecutionContext.getFileOutErr().getErrorStream()) : null;
    // Each invocation of "exec" gets its own sandbox.
    Path sandboxPath = SandboxHelpers.getSandboxRoot(blazeDirs, productName, uuid, execCounter);
    Path sandboxExecRoot = sandboxPath.getRelative("execroot").getRelative(execRoot.getBaseName());
    if (errWriter != null) {
        errWriter.printf("sandbox root is %s\n", sandboxPath.toString());
        errWriter.printf("working dir is %s\n", sandboxExecRoot.toString());
    }
    ImmutableMap<String, String> spawnEnvironment = StandaloneSpawnStrategy.locallyDeterminedEnv(execRoot, productName, spawn.getEnvironment());
    Set<Path> writableDirs = getWritableDirs(sandboxExecRoot, spawn.getEnvironment());
    Path runUnderPath = getRunUnderPath(spawn);
    HardlinkedExecRoot hardlinkedExecRoot = new HardlinkedExecRoot(execRoot, sandboxPath, sandboxExecRoot, errWriter);
    ImmutableSet<PathFragment> outputs = SandboxHelpers.getOutputFiles(spawn);
    try {
        hardlinkedExecRoot.createFileSystem(getMounts(spawn, actionExecutionContext), outputs, writableDirs);
    } catch (IOException e) {
        throw new UserExecException("Could not prepare sandbox directory", e);
    }
    // Flush our logs before executing the spawn, otherwise they might get overwritten.
    if (errWriter != null) {
        errWriter.flush();
    }
    DarwinSandboxRunner runner = new DarwinSandboxRunner(sandboxPath, sandboxExecRoot, getWritableDirs(sandboxExecRoot, spawnEnvironment), getInaccessiblePaths(), runUnderPath, verboseFailures);
    try {
        runSpawn(spawn, actionExecutionContext, spawnEnvironment, hardlinkedExecRoot, outputs, runner, writeOutputFiles);
    } finally {
        if (!sandboxDebug) {
            try {
                FileSystemUtils.deleteTree(sandboxPath);
            } catch (IOException e) {
                executor.getEventHandler().handle(Event.warn(String.format("Cannot delete sandbox directory after action execution: %s (%s)", sandboxPath.getPathString(), e)));
            }
        }
    }
}
Also used : SearchPath(com.google.devtools.build.lib.vfs.SearchPath) Path(com.google.devtools.build.lib.vfs.Path) Executor(com.google.devtools.build.lib.actions.Executor) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) UserExecException(com.google.devtools.build.lib.actions.UserExecException) IOException(java.io.IOException) PrintWriter(java.io.PrintWriter)

Example 4 with UserExecException

use of com.google.devtools.build.lib.actions.UserExecException in project bazel by bazelbuild.

the class LinuxSandboxedStrategy method getReadOnlyBindMounts.

private SortedMap<Path, Path> getReadOnlyBindMounts(BlazeDirectories blazeDirs, Path sandboxExecRoot) throws UserExecException {
    Path tmpPath = blazeDirs.getFileSystem().getPath("/tmp");
    final SortedMap<Path, Path> bindMounts = Maps.newTreeMap();
    if (blazeDirs.getWorkspace().startsWith(tmpPath)) {
        bindMounts.put(blazeDirs.getWorkspace(), blazeDirs.getWorkspace());
    }
    if (blazeDirs.getOutputBase().startsWith(tmpPath)) {
        bindMounts.put(blazeDirs.getOutputBase(), blazeDirs.getOutputBase());
    }
    for (ImmutableMap.Entry<String, String> additionalMountPath : sandboxOptions.sandboxAdditionalMounts) {
        try {
            final Path mountTarget = blazeDirs.getFileSystem().getPath(additionalMountPath.getValue());
            // If source path is relative, treat it as a relative path inside the execution root
            final Path mountSource = sandboxExecRoot.getRelative(additionalMountPath.getKey());
            // If a target has more than one source path, the latter one will take effect.
            bindMounts.put(mountTarget, mountSource);
        } catch (IllegalArgumentException e) {
            throw new UserExecException(String.format("Error occurred when analyzing bind mount pairs. %s", e.getMessage()));
        }
    }
    validateBindMounts(bindMounts);
    return bindMounts;
}
Also used : Path(com.google.devtools.build.lib.vfs.Path) UserExecException(com.google.devtools.build.lib.actions.UserExecException) ImmutableMap(com.google.common.collect.ImmutableMap)

Example 5 with UserExecException

use of com.google.devtools.build.lib.actions.UserExecException in project bazel by bazelbuild.

the class SandboxRunner method run.

/**
   * Runs the command specified via {@code arguments} and {@code env} inside the sandbox.
   *
   * @param arguments - arguments of spawn to run inside the sandbox.
   * @param environment - environment variables to pass to the spawn.
   * @param outErr - error output to capture sandbox's and command's stderr.
   * @param timeout - after how many seconds should the process be killed.
   * @param allowNetwork - whether networking should be allowed for the process.
   * @param sandboxDebug - whether debugging message should be printed.
   * @param useFakeHostname - whether the hostname should be set to 'localhost' inside the sandbox.
   */
void run(List<String> arguments, Map<String, String> environment, OutErr outErr, int timeout, boolean allowNetwork, boolean sandboxDebug, boolean useFakeHostname) throws ExecException {
    Command cmd;
    try {
        cmd = getCommand(arguments, environment, timeout, allowNetwork, useFakeHostname);
    } catch (IOException e) {
        throw new UserExecException("I/O error during sandboxed execution", e);
    }
    TerminationStatus status = null;
    try {
        cmd.execute(/* stdin */
        new byte[] {}, getCommandObserver(timeout), outErr.getOutputStream(), outErr.getErrorStream(), /* killSubprocessOnInterrupt */
        true);
    } catch (CommandException e) {
        boolean timedOut = false;
        if (e instanceof AbnormalTerminationException) {
            status = ((AbnormalTerminationException) e).getResult().getTerminationStatus();
            timedOut = !status.exited() && (status.getTerminatingSignal() == getSignalOnTimeout());
        }
        String statusMessage = status + " [sandboxed]";
        if (!verboseFailures) {
            // simplest error message
            throw new UserExecException(statusMessage, e, timedOut);
        }
        List<String> commandList;
        if (!sandboxDebug) {
            commandList = arguments;
        } else {
            commandList = Arrays.asList(cmd.getCommandLineElements());
        }
        String commandFailureMessage = CommandFailureUtils.describeCommandFailure(true, commandList, environment, null) + (sandboxDebug ? "" : SANDBOX_DEBUG_SUGGESTION);
        throw new UserExecException(commandFailureMessage, e, timedOut);
    }
}
Also used : Command(com.google.devtools.build.lib.shell.Command) TerminationStatus(com.google.devtools.build.lib.shell.TerminationStatus) UserExecException(com.google.devtools.build.lib.actions.UserExecException) AbnormalTerminationException(com.google.devtools.build.lib.shell.AbnormalTerminationException) List(java.util.List) IOException(java.io.IOException) CommandException(com.google.devtools.build.lib.shell.CommandException)

Aggregations

UserExecException (com.google.devtools.build.lib.actions.UserExecException)15 IOException (java.io.IOException)11 Path (com.google.devtools.build.lib.vfs.Path)6 Executor (com.google.devtools.build.lib.actions.Executor)5 AbnormalTerminationException (com.google.devtools.build.lib.shell.AbnormalTerminationException)4 Command (com.google.devtools.build.lib.shell.Command)4 CommandException (com.google.devtools.build.lib.shell.CommandException)4 TerminationStatus (com.google.devtools.build.lib.shell.TerminationStatus)4 ActionInput (com.google.devtools.build.lib.actions.ActionInput)3 EventHandler (com.google.devtools.build.lib.events.EventHandler)3 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)3 ArrayList (java.util.ArrayList)3 ActionResult (com.google.devtools.build.lib.remote.RemoteProtocol.ActionResult)2 CommandResult (com.google.devtools.build.lib.shell.CommandResult)2 FileOutErr (com.google.devtools.build.lib.util.io.FileOutErr)2 WorkResponse (com.google.devtools.build.lib.worker.WorkerProtocol.WorkResponse)2 ByteString (com.google.protobuf.ByteString)2 StatusRuntimeException (io.grpc.StatusRuntimeException)2 ImmutableMap (com.google.common.collect.ImmutableMap)1 HashCode (com.google.common.hash.HashCode)1