use of com.google.devtools.build.lib.util.io.OutErr in project bazel by bazelbuild.
the class SkyframeActionExecutor method dumpRecordedOutErr.
/**
* Dump the output from the action.
*
* @param prefixEvent An event to post before dumping the output
* @param outErrBuffer The OutErr that recorded the actions output
*/
private void dumpRecordedOutErr(Event prefixEvent, FileOutErr outErrBuffer) {
// actions will not be interleaved.
synchronized (reporter) {
// Only print the output if we're not winding down.
if (isBuilderAborting()) {
return;
}
reporter.handle(prefixEvent);
if (outErrBuffer != null && outErrBuffer.hasRecordedOutput()) {
OutErr outErr = this.reporter.getOutErr();
outErrBuffer.dumpOutAsLatin1(outErr.getOutputStream());
outErrBuffer.dumpErrAsLatin1(outErr.getErrorStream());
}
}
}
use of com.google.devtools.build.lib.util.io.OutErr in project bazel by bazelbuild.
the class BlazeCommandDispatcher method execExclusively.
private int execExclusively(List<String> args, OutErr outErr, long firstContactTime, String commandName, BlazeCommand command, long waitTimeInMs) throws ShutdownBlazeServerException {
Command commandAnnotation = command.getClass().getAnnotation(Command.class);
// Record the start time for the profiler. Do not put anything before this!
long execStartTimeNanos = runtime.getClock().nanoTime();
// The initCommand call also records the start time for the timestamp granularity monitor.
CommandEnvironment env = runtime.getWorkspace().initCommand();
// Record the command's starting time for use by the commands themselves.
env.recordCommandStartTime(firstContactTime);
AbruptExitException exitCausingException = null;
for (BlazeModule module : runtime.getBlazeModules()) {
try {
module.beforeCommand(commandAnnotation, env);
} catch (AbruptExitException e) {
// Don't let one module's complaints prevent the other modules from doing necessary
// setup. We promised to call beforeCommand exactly once per-module before each command
// and will be calling afterCommand soon in the future - a module's afterCommand might
// rightfully assume its beforeCommand has already been called.
outErr.printErrLn(e.getMessage());
// It's not ideal but we can only return one exit code, so we just pick the code of the
// last exception.
exitCausingException = e;
}
}
if (exitCausingException != null) {
return exitCausingException.getExitCode().getNumericExitCode();
}
try {
Path commandLog = getCommandLogPath(env.getOutputBase());
// Unlink old command log from previous build, if present, so scripts
// reading it don't conflate it with the command log we're about to write.
closeSilently(logOutputStream);
logOutputStream = null;
commandLog.delete();
if (env.getRuntime().writeCommandLog() && commandAnnotation.writeCommandLog()) {
logOutputStream = commandLog.getOutputStream();
outErr = tee(outErr, OutErr.create(logOutputStream, logOutputStream));
}
} catch (IOException ioException) {
LoggingUtil.logToRemote(Level.WARNING, "Unable to delete or open command.log", ioException);
}
ExitCode result = checkCwdInWorkspace(env, commandAnnotation, commandName, outErr);
if (!result.equals(ExitCode.SUCCESS)) {
return result.getNumericExitCode();
}
OptionsParser optionsParser;
// Delay output of notes regarding the parsed rc file, so it's possible to disable this in the
// rc file.
List<String> rcfileNotes = new ArrayList<>();
try {
optionsParser = createOptionsParser(command);
parseArgsAndConfigs(env, optionsParser, commandAnnotation, args, rcfileNotes, outErr);
InvocationPolicyEnforcer optionsPolicyEnforcer = new InvocationPolicyEnforcer(runtime.getInvocationPolicy());
optionsPolicyEnforcer.enforce(optionsParser, commandName);
optionsPolicyEnforcer = InvocationPolicyEnforcer.create(getRuntime().getStartupOptionsProvider().getOptions(BlazeServerStartupOptions.class).invocationPolicy);
optionsPolicyEnforcer.enforce(optionsParser, commandName);
} catch (OptionsParsingException e) {
for (String note : rcfileNotes) {
outErr.printErrLn("INFO: " + note);
}
outErr.printErrLn(e.getMessage());
return ExitCode.COMMAND_LINE_ERROR.getNumericExitCode();
}
// Setup log filtering
BlazeCommandEventHandler.Options eventHandlerOptions = optionsParser.getOptions(BlazeCommandEventHandler.Options.class);
OutErr colorfulOutErr = outErr;
if (!eventHandlerOptions.useColor()) {
outErr = ansiStripOut(ansiStripErr(outErr));
if (!commandAnnotation.binaryStdOut()) {
colorfulOutErr = ansiStripOut(colorfulOutErr);
}
if (!commandAnnotation.binaryStdErr()) {
colorfulOutErr = ansiStripErr(colorfulOutErr);
}
}
if (!commandAnnotation.binaryStdOut()) {
outErr = lineBufferOut(outErr);
}
if (!commandAnnotation.binaryStdErr()) {
outErr = lineBufferErr(outErr);
}
CommonCommandOptions commonOptions = optionsParser.getOptions(CommonCommandOptions.class);
if (!commonOptions.verbosity.equals(lastLogVerbosityLevel)) {
BlazeRuntime.setupLogging(commonOptions.verbosity);
lastLogVerbosityLevel = commonOptions.verbosity;
}
// Do this before an actual crash so we don't have to worry about
// allocating memory post-crash.
String[] crashData = env.getCrashData();
int numericExitCode = ExitCode.BLAZE_INTERNAL_ERROR.getNumericExitCode();
PrintStream savedOut = System.out;
PrintStream savedErr = System.err;
EventHandler handler = createEventHandler(outErr, eventHandlerOptions);
Reporter reporter = env.getReporter();
reporter.addHandler(handler);
env.getEventBus().register(handler);
// We register an ANSI-allowing handler associated with {@code handler} so that ANSI control
// codes can be re-introduced later even if blaze is invoked with --color=no. This is useful
// for commands such as 'blaze run' where the output of the final executable shouldn't be
// modified.
EventHandler ansiAllowingHandler = null;
if (!eventHandlerOptions.useColor()) {
ansiAllowingHandler = createEventHandler(colorfulOutErr, eventHandlerOptions);
reporter.registerAnsiAllowingHandler(handler, ansiAllowingHandler);
if (ansiAllowingHandler instanceof ExperimentalEventHandler) {
env.getEventBus().register(new PassiveExperimentalEventHandler((ExperimentalEventHandler) ansiAllowingHandler));
}
}
try {
// While a Blaze command is active, direct all errors to the client's
// event handler (and out/err streams).
OutErr reporterOutErr = reporter.getOutErr();
System.setOut(new PrintStream(reporterOutErr.getOutputStream(), /*autoflush=*/
true));
System.setErr(new PrintStream(reporterOutErr.getErrorStream(), /*autoflush=*/
true));
for (BlazeModule module : runtime.getBlazeModules()) {
module.checkEnvironment(env);
}
if (commonOptions.announceRcOptions) {
for (String note : rcfileNotes) {
reporter.handle(Event.info(note));
}
}
try {
// Notify the BlazeRuntime, so it can do some initial setup.
env.beforeCommand(commandAnnotation, optionsParser, commonOptions, execStartTimeNanos, waitTimeInMs);
// Allow the command to edit options after parsing:
command.editOptions(env, optionsParser);
} catch (AbruptExitException e) {
reporter.handle(Event.error(e.getMessage()));
return e.getExitCode().getNumericExitCode();
}
for (BlazeModule module : runtime.getBlazeModules()) {
module.handleOptions(optionsParser);
}
// Print warnings for odd options usage
for (String warning : optionsParser.getWarnings()) {
reporter.handle(Event.warn(warning));
}
ExitCode outcome = command.exec(env, optionsParser);
outcome = env.precompleteCommand(outcome);
numericExitCode = outcome.getNumericExitCode();
return numericExitCode;
} catch (ShutdownBlazeServerException e) {
numericExitCode = e.getExitStatus();
throw e;
} catch (Throwable e) {
e.printStackTrace();
BugReport.printBug(outErr, e);
BugReport.sendBugReport(e, args, crashData);
numericExitCode = BugReport.getExitCodeForThrowable(e);
throw new ShutdownBlazeServerException(numericExitCode, e);
} finally {
env.getEventBus().post(new AfterCommandEvent());
runtime.afterCommand(env, numericExitCode);
// Swallow IOException, as we are already in a finally clause
Flushables.flushQuietly(outErr.getOutputStream());
Flushables.flushQuietly(outErr.getErrorStream());
System.setOut(savedOut);
System.setErr(savedErr);
reporter.removeHandler(handler);
releaseHandler(handler);
if (!eventHandlerOptions.useColor()) {
reporter.removeHandler(ansiAllowingHandler);
releaseHandler(ansiAllowingHandler);
}
env.getTimestampGranularityMonitor().waitForTimestampGranularity(outErr);
}
}
use of com.google.devtools.build.lib.util.io.OutErr in project bazel by bazelbuild.
the class InfoCommand method exec.
@Override
public ExitCode exec(final CommandEnvironment env, final OptionsProvider optionsProvider) {
final BlazeRuntime runtime = env.getRuntime();
env.getReporter().switchToAnsiAllowingHandler();
Options infoOptions = optionsProvider.getOptions(Options.class);
OutErr outErr = env.getReporter().getOutErr();
// Creating a BuildConfiguration is expensive and often unnecessary. Delay the creation until
// it is needed.
Supplier<BuildConfiguration> configurationSupplier = new Supplier<BuildConfiguration>() {
private BuildConfiguration configuration;
@Override
public BuildConfiguration get() {
if (configuration != null) {
return configuration;
}
try {
// In order to be able to answer configuration-specific queries, we need to setup the
// package path. Since info inherits all the build options, all the necessary information
// is available here.
env.setupPackageCache(optionsProvider, runtime.getDefaultsPackageContent(optionsProvider));
// TODO(bazel-team): What if there are multiple configurations? [multi-config]
configuration = env.getConfigurations(optionsProvider).getTargetConfigurations().get(0);
return configuration;
} catch (InvalidConfigurationException e) {
env.getReporter().handle(Event.error(e.getMessage()));
throw new ExitCausingRuntimeException(ExitCode.COMMAND_LINE_ERROR);
} catch (AbruptExitException e) {
throw new ExitCausingRuntimeException("unknown error: " + e.getMessage(), e.getExitCode());
} catch (InterruptedException e) {
env.getReporter().handle(Event.error("interrupted"));
throw new ExitCausingRuntimeException(ExitCode.INTERRUPTED);
}
}
};
Map<String, InfoItem> items = getInfoItemMap(env, optionsProvider);
try {
if (infoOptions.showMakeEnvironment) {
Map<String, String> makeEnv = configurationSupplier.get().getMakeEnvironment();
for (Map.Entry<String, String> entry : makeEnv.entrySet()) {
InfoItem item = new InfoItem.MakeInfoItem(entry.getKey(), entry.getValue());
items.put(item.getName(), item);
}
}
List<String> residue = optionsProvider.getResidue();
if (residue.size() > 1) {
env.getReporter().handle(Event.error("at most one key may be specified"));
return ExitCode.COMMAND_LINE_ERROR;
}
String key = residue.size() == 1 ? residue.get(0) : null;
env.getEventBus().post(new NoBuildEvent());
if (key != null) {
// print just the value for the specified key:
byte[] value;
if (items.containsKey(key)) {
value = items.get(key).get(configurationSupplier, env);
} else {
env.getReporter().handle(Event.error("unknown key: '" + key + "'"));
return ExitCode.COMMAND_LINE_ERROR;
}
try {
outErr.getOutputStream().write(value);
outErr.getOutputStream().flush();
} catch (IOException e) {
env.getReporter().handle(Event.error("Cannot write info block: " + e.getMessage()));
return ExitCode.ANALYSIS_FAILURE;
}
} else {
// print them all
// We'll need this later anyway
configurationSupplier.get();
for (InfoItem infoItem : items.values()) {
if (infoItem.isHidden()) {
continue;
}
outErr.getOutputStream().write((infoItem.getName() + ": ").getBytes(StandardCharsets.UTF_8));
outErr.getOutputStream().write(infoItem.get(configurationSupplier, env));
}
}
} catch (AbruptExitException e) {
return e.getExitCode();
} catch (ExitCausingRuntimeException e) {
return e.getExitCode();
} catch (IOException e) {
return ExitCode.LOCAL_ENVIRONMENTAL_ERROR;
} catch (InterruptedException e) {
return ExitCode.INTERRUPTED;
}
return ExitCode.SUCCESS;
}
use of com.google.devtools.build.lib.util.io.OutErr in project bazel by bazelbuild.
the class SandboxStrategy method runSpawn.
protected void runSpawn(Spawn spawn, ActionExecutionContext actionExecutionContext, Map<String, String> spawnEnvironment, SandboxExecRoot sandboxExecRoot, Set<PathFragment> outputs, SandboxRunner runner, AtomicReference<Class<? extends SpawnActionContext>> writeOutputFiles) throws ExecException, InterruptedException {
EventHandler eventHandler = actionExecutionContext.getExecutor().getEventHandler();
ExecException execException = null;
OutErr outErr = actionExecutionContext.getFileOutErr();
try {
runner.run(spawn.getArguments(), spawnEnvironment, outErr, Spawns.getTimeoutSeconds(spawn), SandboxHelpers.shouldAllowNetwork(buildRequest, spawn), sandboxOptions.sandboxDebug, sandboxOptions.sandboxFakeHostname);
} catch (ExecException e) {
execException = e;
}
if (writeOutputFiles != null && !writeOutputFiles.compareAndSet(null, SandboxStrategy.class)) {
throw new InterruptedException();
}
try {
// We copy the outputs even when the command failed, otherwise StandaloneTestStrategy
// won't be able to get the test logs of a failed test. (We should probably do this in
// some better way.)
sandboxExecRoot.copyOutputs(execRoot, outputs);
} catch (IOException e) {
if (execException == null) {
throw new UserExecException("Could not move output artifacts from sandboxed execution", e);
} else {
// Catch the IOException and turn it into an error message, otherwise this might hide an
// exception thrown during runner.run earlier.
eventHandler.handle(Event.error("I/O exception while extracting output artifacts from sandboxed execution: " + e));
}
}
if (execException != null) {
outErr.printErr("Use --strategy=" + spawn.getMnemonic() + "=standalone to disable sandboxing for the failing actions.\n");
throw execException;
}
}
use of com.google.devtools.build.lib.util.io.OutErr in project bazel by bazelbuild.
the class GrpcServerImpl method executeCommand.
private void executeCommand(RunRequest request, StreamObserver<RunResponse> observer, GrpcSink sink) {
sink.setCommandThread(Thread.currentThread());
if (!request.getCookie().equals(requestCookie) || request.getClientDescription().isEmpty()) {
try {
observer.onNext(RunResponse.newBuilder().setExitCode(ExitCode.LOCAL_ENVIRONMENTAL_ERROR.getNumericExitCode()).build());
observer.onCompleted();
} catch (StatusRuntimeException e) {
log.info("Client cancelled command while rejecting it: " + e.getMessage());
}
return;
}
// case by explicitly checking for disconnection here.
if (sink.disconnected()) {
return;
}
ImmutableList.Builder<String> args = ImmutableList.builder();
for (ByteString requestArg : request.getArgList()) {
args.add(requestArg.toString(CHARSET));
}
String commandId;
int exitCode;
try (RunningCommand command = new RunningCommand()) {
commandId = command.id;
try {
// Send the client the command id as soon as we know it.
observer.onNext(RunResponse.newBuilder().setCookie(responseCookie).setCommandId(commandId).build());
} catch (StatusRuntimeException e) {
log.info("The client cancelled the command before receiving the command id: " + e.getMessage());
}
OutErr rpcOutErr = OutErr.create(new RpcOutputStream(command.id, responseCookie, StreamType.STDOUT, sink), new RpcOutputStream(command.id, responseCookie, StreamType.STDERR, sink));
exitCode = commandExecutor.exec(args.build(), rpcOutErr, request.getBlockForLock() ? LockingMode.WAIT : LockingMode.ERROR_OUT, request.getClientDescription(), clock.currentTimeMillis());
} catch (InterruptedException e) {
exitCode = ExitCode.INTERRUPTED.getNumericExitCode();
// The default value, the client will ignore it
commandId = "";
}
if (sink.finish()) {
// Client disconnected. Then we are not allowed to call any methods on the observer.
log.info(String.format("Client disconnected before we could send exit code for command %s", commandId));
return;
}
// There is a chance that an Uninterruptibles#getUninterruptibly() leaves us with the
// interrupt bit set. So we just reset the interruption state here to make these cancel
// requests not have any effect outside of command execution (after the try block above,
// the cancel request won't find the thread to interrupt)
Thread.interrupted();
RunResponse response = RunResponse.newBuilder().setCookie(responseCookie).setCommandId(commandId).setFinished(true).setExitCode(exitCode).build();
try {
observer.onNext(response);
observer.onCompleted();
} catch (StatusRuntimeException e) {
// The client cancelled the call. Log an error and go on.
log.info(String.format("Client cancelled command %s just right before its end: %s", commandId, e.getMessage()));
}
if (commandExecutor.shutdown()) {
pidFileWatcherThread.signalShutdown();
server.shutdown();
}
}
Aggregations