Search in sources :

Example 6 with WorkRequest

use of com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest in project bazel by bazelbuild.

the class WorkerSpawnStrategy method actuallyExec.

private void actuallyExec(Spawn spawn, ActionExecutionContext actionExecutionContext, AtomicReference<Class<? extends SpawnActionContext>> writeOutputFiles) throws ExecException, InterruptedException {
    Executor executor = actionExecutionContext.getExecutor();
    EventHandler eventHandler = executor.getEventHandler();
    if (executor.reportsSubcommands()) {
        executor.reportSubcommand(spawn);
    }
    // We assume that the spawn to be executed always gets at least one @flagfile.txt or
    // --flagfile=flagfile.txt argument, which contains the flags related to the work itself (as
    // opposed to start-up options for the executed tool). Thus, we can extract those elements from
    // its args and put them into the WorkRequest instead.
    List<String> flagfiles = new ArrayList<>();
    List<String> startupArgs = new ArrayList<>();
    for (String arg : spawn.getArguments()) {
        if (FLAG_FILE_PATTERN.matcher(arg).matches()) {
            flagfiles.add(arg);
        } else {
            startupArgs.add(arg);
        }
    }
    if (flagfiles.isEmpty()) {
        throw new UserExecException(String.format(ERROR_MESSAGE_PREFIX + REASON_NO_FLAGFILE, spawn.getMnemonic()));
    }
    if (Iterables.isEmpty(spawn.getToolFiles())) {
        throw new UserExecException(String.format(ERROR_MESSAGE_PREFIX + REASON_NO_TOOLS, spawn.getMnemonic()));
    }
    FileOutErr outErr = actionExecutionContext.getFileOutErr();
    ImmutableList<String> args = ImmutableList.<String>builder().addAll(startupArgs).add("--persistent_worker").addAll(MoreObjects.firstNonNull(extraFlags.get(spawn.getMnemonic()), ImmutableList.<String>of())).build();
    ImmutableMap<String, String> env = spawn.getEnvironment();
    try {
        ActionInputFileCache inputFileCache = actionExecutionContext.getActionInputFileCache();
        HashCode workerFilesHash = WorkerFilesHash.getWorkerFilesHash(spawn.getToolFiles(), actionExecutionContext);
        Map<PathFragment, Path> inputFiles = new SpawnHelpers(execRoot).getMounts(spawn, actionExecutionContext);
        Set<PathFragment> outputFiles = SandboxHelpers.getOutputFiles(spawn);
        WorkerKey key = new WorkerKey(args, env, execRoot, spawn.getMnemonic(), workerFilesHash, inputFiles, outputFiles, writeOutputFiles != null);
        WorkRequest.Builder requestBuilder = WorkRequest.newBuilder();
        for (String flagfile : flagfiles) {
            expandArgument(requestBuilder, flagfile);
        }
        List<ActionInput> inputs = ActionInputHelper.expandArtifacts(spawn.getInputFiles(), actionExecutionContext.getArtifactExpander());
        for (ActionInput input : inputs) {
            byte[] digestBytes = inputFileCache.getDigest(input);
            ByteString digest;
            if (digestBytes == null) {
                digest = ByteString.EMPTY;
            } else {
                digest = ByteString.copyFromUtf8(HashCode.fromBytes(digestBytes).toString());
            }
            requestBuilder.addInputsBuilder().setPath(input.getExecPathString()).setDigest(digest).build();
        }
        WorkResponse response = execInWorker(eventHandler, key, requestBuilder.build(), maxRetries, writeOutputFiles);
        outErr.getErrorStream().write(response.getOutputBytes().toByteArray());
        if (response.getExitCode() != 0) {
            throw new UserExecException(String.format("Worker process sent response with exit code: %d.", response.getExitCode()));
        }
    } catch (IOException e) {
        String message = CommandFailureUtils.describeCommandFailure(verboseFailures, spawn.getArguments(), env, execRoot.getPathString());
        throw new UserExecException(message, e);
    }
}
Also used : FileOutErr(com.google.devtools.build.lib.util.io.FileOutErr) ActionInput(com.google.devtools.build.lib.actions.ActionInput) ByteString(com.google.protobuf.ByteString) ArrayList(java.util.ArrayList) PathFragment(com.google.devtools.build.lib.vfs.PathFragment) EventHandler(com.google.devtools.build.lib.events.EventHandler) ByteString(com.google.protobuf.ByteString) Executor(com.google.devtools.build.lib.actions.Executor) HashCode(com.google.common.hash.HashCode) Path(com.google.devtools.build.lib.vfs.Path) SpawnHelpers(com.google.devtools.build.lib.sandbox.SpawnHelpers) UserExecException(com.google.devtools.build.lib.actions.UserExecException) IOException(java.io.IOException) ActionInputFileCache(com.google.devtools.build.lib.actions.ActionInputFileCache) WorkRequest(com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest) WorkResponse(com.google.devtools.build.lib.worker.WorkerProtocol.WorkResponse)

Example 7 with WorkRequest

use of com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest in project bazel by bazelbuild.

the class ExampleWorker method runPersistentWorker.

private static void runPersistentWorker(ExampleWorkerOptions workerOptions) throws IOException {
    PrintStream originalStdOut = System.out;
    PrintStream originalStdErr = System.err;
    while (true) {
        try {
            WorkRequest request = WorkRequest.parseDelimitedFrom(System.in);
            if (request == null) {
                break;
            }
            inputs.clear();
            for (Input input : request.getInputsList()) {
                inputs.put(input.getPath(), input.getDigest().toStringUtf8());
            }
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            int exitCode = 0;
            try (PrintStream ps = new PrintStream(baos)) {
                System.setOut(ps);
                System.setErr(ps);
                if (poisoned) {
                    System.out.println("I'm a poisoned worker and this is not a protobuf.");
                    System.out.println("Here's a fake stack trace for you:");
                    System.out.println("    at com.example.Something(Something.java:83)");
                    System.out.println("    at java.lang.Thread.run(Thread.java:745)");
                    System.out.print("And now, 8k of random bytes: ");
                    byte[] b = new byte[8192];
                    new Random().nextBytes(b);
                    System.out.write(b);
                } else {
                    try {
                        processRequest(request.getArgumentsList());
                    } catch (Exception e) {
                        e.printStackTrace();
                        exitCode = 1;
                    }
                }
            } finally {
                System.setOut(originalStdOut);
                System.setErr(originalStdErr);
            }
            if (poisoned) {
                baos.writeTo(System.out);
            } else {
                WorkResponse.newBuilder().setOutput(baos.toString()).setExitCode(exitCode).build().writeDelimitedTo(System.out);
            }
            System.out.flush();
            if (workerOptions.exitAfter > 0 && workUnitCounter > workerOptions.exitAfter) {
                return;
            }
            if (workerOptions.poisonAfter > 0 && workUnitCounter > workerOptions.poisonAfter) {
                poisoned = true;
            }
        } finally {
            // Be a good worker process and consume less memory when idle.
            System.gc();
        }
    }
}
Also used : PrintStream(java.io.PrintStream) WorkRequest(com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest) Input(com.google.devtools.build.lib.worker.WorkerProtocol.Input) Random(java.util.Random) ByteArrayOutputStream(java.io.ByteArrayOutputStream) IOException(java.io.IOException)

Example 8 with WorkRequest

use of com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest in project bazel by bazelbuild.

the class DexBuilder method runPersistentWorker.

/**
   * Implements a persistent worker process for use with Bazel (see {@code WorkerSpawnStrategy}).
   */
private static void runPersistentWorker() throws IOException {
    ExecutorService executor = newFixedThreadPool(Runtime.getRuntime().availableProcessors());
    Cache<DexingKey, byte[]> dexCache = CacheBuilder.newBuilder().maximumWeight(Math.min(Runtime.getRuntime().maxMemory() - 25 * ONE_MEG, 200 * ONE_MEG)).weigher(new Weigher<DexingKey, byte[]>() {

        @Override
        public int weigh(DexingKey key, byte[] value) {
            return key.classfileContent().length + value.length;
        }
    }).build();
    try {
        while (true) {
            WorkRequest request = WorkRequest.parseDelimitedFrom(System.in);
            if (request == null) {
                return;
            }
            // Redirect dx's output so we can return it in response
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            PrintStream ps = new PrintStream(baos, /*autoFlush*/
            true);
            DxConsole.out = DxConsole.err = ps;
            // Make sure that we exit nonzero in case uncaught errors occur during processRequest.
            int exitCode = 1;
            try {
                processRequest(executor, dexCache, request.getArgumentsList());
                // success!
                exitCode = 0;
            } catch (Exception e) {
                // Deliberate catch-all so we can capture a stack trace.
                // TODO(bazel-team): Consider canceling any outstanding futures created for this request
                e.printStackTrace(ps);
            } catch (Error e) {
                e.printStackTrace();
                // try capturing the error, may fail if out of memory
                e.printStackTrace(ps);
                // rethrow to kill the worker
                throw e;
            } finally {
                // Try sending a response no matter what
                String output;
                try {
                    output = baos.toString();
                } catch (Throwable t) {
                    // most likely out of memory, so log with minimal memory needs
                    t.printStackTrace();
                    output = "check worker log for exceptions";
                }
                WorkResponse.newBuilder().setOutput(output).setExitCode(exitCode).build().writeDelimitedTo(System.out);
                System.out.flush();
            }
        }
    } finally {
        executor.shutdown();
    }
}
Also used : WorkRequest(com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest) PrintStream(java.io.PrintStream) Weigher(com.google.common.cache.Weigher) ExecutorService(java.util.concurrent.ExecutorService) ByteArrayOutputStream(java.io.ByteArrayOutputStream) DexingKey(com.google.devtools.build.android.dexer.Dexing.DexingKey) IOException(java.io.IOException) OptionsParsingException(com.google.devtools.common.options.OptionsParsingException) ExecutionException(java.util.concurrent.ExecutionException)

Aggregations

WorkRequest (com.google.devtools.build.lib.worker.WorkerProtocol.WorkRequest)8 IOException (java.io.IOException)7 WorkResponse (com.google.devtools.build.lib.worker.WorkerProtocol.WorkResponse)4 ByteArrayOutputStream (java.io.ByteArrayOutputStream)3 PrintStream (java.io.PrintStream)3 HashCode (com.google.common.hash.HashCode)2 Executor (com.google.devtools.build.lib.actions.Executor)2 Path (com.google.devtools.build.lib.vfs.Path)2 PathFragment (com.google.devtools.build.lib.vfs.PathFragment)2 Weigher (com.google.common.cache.Weigher)1 DexingKey (com.google.devtools.build.android.dexer.Dexing.DexingKey)1 ActionInput (com.google.devtools.build.lib.actions.ActionInput)1 ActionInputFileCache (com.google.devtools.build.lib.actions.ActionInputFileCache)1 TestExecException (com.google.devtools.build.lib.actions.TestExecException)1 UserExecException (com.google.devtools.build.lib.actions.UserExecException)1 EventHandler (com.google.devtools.build.lib.events.EventHandler)1 SpawnHelpers (com.google.devtools.build.lib.sandbox.SpawnHelpers)1 FileOutErr (com.google.devtools.build.lib.util.io.FileOutErr)1 TestCase (com.google.devtools.build.lib.view.test.TestStatus.TestCase)1 TestResultData (com.google.devtools.build.lib.view.test.TestStatus.TestResultData)1