use of com.google.devtools.build.lib.util.AbruptExitException in project bazel by bazelbuild.
the class BuildTool method processRequest.
/**
* The crux of the build system. Builds the targets specified in the request using the specified
* Executor.
*
* <p>Performs loading, analysis and execution for the specified set of targets, honoring the
* configuration options in the BuildRequest. Returns normally iff successful, throws an exception
* otherwise.
*
* <p>The caller is responsible for setting up and syncing the package cache.
*
* <p>During this function's execution, the actualTargets and successfulTargets
* fields of the request object are set.
*
* @param request the build request that this build tool is servicing, which specifies various
* options; during this method's execution, the actualTargets and successfulTargets fields
* of the request object are populated
* @param validator target validator
* @return the result as a {@link BuildResult} object
*/
public BuildResult processRequest(BuildRequest request, TargetValidator validator) {
BuildResult result = new BuildResult(request.getStartTime());
env.getEventBus().register(result);
maybeSetStopOnFirstFailure(request, result);
Throwable catastrophe = null;
ExitCode exitCode = ExitCode.BLAZE_INTERNAL_ERROR;
try {
buildTargets(request, result, validator);
exitCode = ExitCode.SUCCESS;
} catch (BuildFailedException e) {
if (e.isErrorAlreadyShown()) {
// The actual error has already been reported by the Builder.
} else {
reportExceptionError(e);
}
if (e.isCatastrophic()) {
result.setCatastrophe();
}
exitCode = e.getExitCode() != null ? e.getExitCode() : ExitCode.BUILD_FAILURE;
} catch (InterruptedException e) {
// We may have been interrupted by an error, or the user's interruption may have raced with
// an error, so check to see if we should report that error code instead.
exitCode = env.getPendingExitCode();
if (exitCode == null) {
exitCode = ExitCode.INTERRUPTED;
env.getReporter().handle(Event.error("build interrupted"));
env.getEventBus().post(new BuildInterruptedEvent());
} else {
// Report the exception from the environment - the exception we're handling here is just an
// interruption.
reportExceptionError(env.getPendingException());
result.setCatastrophe();
}
} catch (TargetParsingException | LoadingFailedException | ViewCreationFailedException e) {
exitCode = ExitCode.PARSING_FAILURE;
reportExceptionError(e);
} catch (TestExecException e) {
// ExitCode.SUCCESS means that build was successful. Real return code of program
// is going to be calculated in TestCommand.doTest().
exitCode = ExitCode.SUCCESS;
reportExceptionError(e);
} catch (InvalidConfigurationException e) {
exitCode = ExitCode.COMMAND_LINE_ERROR;
reportExceptionError(e);
// TODO(gregce): With "global configurations" we cannot tie a configuration creation failure
// to a single target and have to halt the entire build. Once configurations are genuinely
// created as part of the analysis phase they should report their error on the level of the
// target(s) that triggered them.
result.setCatastrophe();
} catch (AbruptExitException e) {
exitCode = e.getExitCode();
reportExceptionError(e);
result.setCatastrophe();
} catch (Throwable throwable) {
catastrophe = throwable;
Throwables.propagate(throwable);
} finally {
stopRequest(result, catastrophe, exitCode);
}
return result;
}
use of com.google.devtools.build.lib.util.AbruptExitException in project bazel by bazelbuild.
the class FetchCommand method exec.
@Override
public ExitCode exec(CommandEnvironment env, OptionsProvider options) {
BlazeRuntime runtime = env.getRuntime();
if (options.getResidue().isEmpty()) {
env.getReporter().handle(Event.error(String.format("missing fetch expression. Type '%s help fetch' for syntax and help", env.getRuntime().getProductName())));
return ExitCode.COMMAND_LINE_ERROR;
}
try {
env.setupPackageCache(options, runtime.getDefaultsPackageContent());
} catch (InterruptedException e) {
env.getReporter().handle(Event.error("fetch interrupted"));
return ExitCode.INTERRUPTED;
} catch (AbruptExitException e) {
env.getReporter().handle(Event.error(null, "Unknown error: " + e.getMessage()));
return e.getExitCode();
}
PackageCacheOptions pkgOptions = options.getOptions(PackageCacheOptions.class);
if (!pkgOptions.fetch) {
env.getReporter().handle(Event.error(null, "You cannot run fetch with --fetch=false"));
return ExitCode.COMMAND_LINE_ERROR;
}
// Querying for all of the dependencies of the targets has the side-effect of populating the
// Skyframe graph for external targets, which requires downloading them. The JDK is required to
// build everything but isn't counted as a dep in the build graph so we add it manually.
ImmutableList.Builder<String> labelsToLoad = new ImmutableList.Builder<String>().addAll(options.getResidue());
String query = Joiner.on(" union ").join(labelsToLoad.build());
query = "deps(" + query + ")";
AbstractBlazeQueryEnvironment<Target> queryEnv = QueryCommand.newQueryEnvironment(env, options.getOptions(FetchOptions.class).keepGoing, false, Lists.<String>newArrayList(), 200, Sets.<Setting>newHashSet());
// 1. Parse query:
QueryExpression expr;
try {
expr = QueryExpression.parse(query, queryEnv);
} catch (QueryException e) {
env.getReporter().handle(Event.error(null, "Error while parsing '" + query + "': " + e.getMessage()));
return ExitCode.COMMAND_LINE_ERROR;
}
// 2. Evaluate expression:
try {
queryEnv.evaluateQuery(expr, new ThreadSafeOutputFormatterCallback<Target>() {
@Override
public void processOutput(Iterable<Target> partialResult) {
// Throw away the result.
}
});
} catch (InterruptedException e) {
return ExitCode.COMMAND_LINE_ERROR;
} catch (QueryException e) {
// Keep consistent with reportBuildFileError()
env.getReporter().handle(Event.error(e.getMessage()));
return ExitCode.COMMAND_LINE_ERROR;
} catch (IOException e) {
// Should be impossible since our OutputFormatterCallback doesn't throw IOException.
throw new IllegalStateException(e);
}
env.getReporter().handle(Event.progress("All external dependencies fetched successfully."));
return ExitCode.SUCCESS;
}
use of com.google.devtools.build.lib.util.AbruptExitException 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.AbruptExitException in project bazel by bazelbuild.
the class BlazeRuntime method newRuntime.
/**
* Creates a new blaze runtime, given the install and output base directories.
*
* <p>Note: This method can and should only be called once per startup, as it also creates the
* filesystem object that will be used for the runtime. So it should only ever be called from the
* main method of the Blaze program.
*
* @param args Blaze startup options.
*
* @return a new BlazeRuntime instance initialized with the given filesystem and directories, and
* an error string that, if not null, describes a fatal initialization failure that makes
* this runtime unsuitable for real commands
*/
private static BlazeRuntime newRuntime(Iterable<BlazeModule> blazeModules, List<String> args, Runnable abruptShutdownHandler) throws AbruptExitException, OptionsParsingException {
OptionsProvider options = parseOptions(blazeModules, args);
for (BlazeModule module : blazeModules) {
module.globalInit(options);
}
BlazeServerStartupOptions startupOptions = options.getOptions(BlazeServerStartupOptions.class);
String productName = startupOptions.productName.toLowerCase(Locale.US);
if (startupOptions.oomMoreEagerlyThreshold != 100) {
new RetainedHeapLimiter(startupOptions.oomMoreEagerlyThreshold).install();
}
PathFragment workspaceDirectory = startupOptions.workspaceDirectory;
PathFragment installBase = startupOptions.installBase;
PathFragment outputBase = startupOptions.outputBase;
// Must be before first use of JNI.
maybeForceJNI(installBase);
// are mandatory options, despite the comment in their declarations.
if (installBase == null || !installBase.isAbsolute()) {
// (includes "" default case)
throw new IllegalArgumentException("Bad --install_base option specified: '" + installBase + "'");
}
if (outputBase != null && !outputBase.isAbsolute()) {
// (includes "" default case)
throw new IllegalArgumentException("Bad --output_base option specified: '" + outputBase + "'");
}
FileSystem fs = null;
for (BlazeModule module : blazeModules) {
FileSystem moduleFs = module.getFileSystem(options);
if (moduleFs != null) {
Preconditions.checkState(fs == null, "more than one module returns a file system");
fs = moduleFs;
}
}
if (fs == null) {
fs = fileSystemImplementation();
}
Path.setFileSystemForSerialization(fs);
SubprocessBuilder.setSubprocessFactory(subprocessFactoryImplementation());
Path installBasePath = fs.getPath(installBase);
Path outputBasePath = fs.getPath(outputBase);
Path workspaceDirectoryPath = null;
if (!workspaceDirectory.equals(PathFragment.EMPTY_FRAGMENT)) {
workspaceDirectoryPath = fs.getPath(workspaceDirectory);
}
ServerDirectories serverDirectories = new ServerDirectories(installBasePath, outputBasePath, startupOptions.installMD5);
Clock clock = BlazeClock.instance();
BlazeRuntime.Builder runtimeBuilder = new BlazeRuntime.Builder().setProductName(productName).setServerDirectories(serverDirectories).setStartupOptionsProvider(options).setClock(clock).setAbruptShutdownHandler(abruptShutdownHandler).setEventBusExceptionHandler(startupOptions.fatalEventBusExceptions || !BlazeVersionInfo.instance().isReleasedBlaze() ? new BlazeRuntime.BugReportingExceptionHandler() : new BlazeRuntime.RemoteExceptionHandler());
if (System.getenv("TEST_TMPDIR") != null && System.getenv("NO_CRASH_ON_LOGGING_IN_TEST") == null) {
LoggingUtil.installRemoteLogger(getTestCrashLogger());
}
runtimeBuilder.addBlazeModule(new BuiltinCommandModule());
for (BlazeModule blazeModule : blazeModules) {
runtimeBuilder.addBlazeModule(blazeModule);
}
BlazeRuntime runtime = runtimeBuilder.build();
BlazeDirectories directories = new BlazeDirectories(serverDirectories, workspaceDirectoryPath, startupOptions.deepExecRoot, productName);
BinTools binTools;
try {
binTools = BinTools.forProduction(directories);
} catch (IOException e) {
throw new AbruptExitException("Cannot enumerate embedded binaries: " + e.getMessage(), ExitCode.LOCAL_ENVIRONMENTAL_ERROR);
}
runtime.initWorkspace(directories, binTools);
if (startupOptions.useCustomExitCodeOnAbruptExit) {
CustomExitCodePublisher.setAbruptExitStatusFileDir(serverDirectories.getOutputBase());
}
AutoProfiler.setClock(runtime.getClock());
BugReport.setRuntime(runtime);
return runtime;
}
use of com.google.devtools.build.lib.util.AbruptExitException in project bazel by bazelbuild.
the class BlazeRuntime method createBlazeRPCServer.
/**
* Creates and returns a new Blaze RPCServer. Call {@link RPCServer#serve()} to start the server.
*/
private static RPCServer createBlazeRPCServer(Iterable<BlazeModule> modules, List<String> args) throws IOException, OptionsParsingException, AbruptExitException {
final RPCServer[] rpcServer = new RPCServer[1];
Runnable prepareForAbruptShutdown = new Runnable() {
@Override
public void run() {
rpcServer[0].prepareForAbruptShutdown();
}
};
BlazeRuntime runtime = newRuntime(modules, args, prepareForAbruptShutdown);
BlazeCommandDispatcher dispatcher = new BlazeCommandDispatcher(runtime);
CommandExecutor commandExecutor = new CommandExecutor(runtime, dispatcher);
BlazeServerStartupOptions startupOptions = runtime.getStartupOptionsProvider().getOptions(BlazeServerStartupOptions.class);
try {
// This is necessary so that Bazel kind of works during bootstrapping, at which time the
// gRPC server is not compiled in so that we don't need gRPC for bootstrapping.
Class<?> factoryClass = Class.forName("com.google.devtools.build.lib.server.GrpcServerImpl$Factory");
RPCServer.Factory factory = (RPCServer.Factory) factoryClass.getConstructor().newInstance();
rpcServer[0] = factory.create(commandExecutor, runtime.getClock(), startupOptions.commandPort, runtime.getWorkspace().getWorkspace(), runtime.getServerDirectory(), startupOptions.maxIdleSeconds);
return rpcServer[0];
} catch (ReflectiveOperationException | IllegalArgumentException e) {
throw new AbruptExitException("gRPC server not compiled in", ExitCode.BLAZE_INTERNAL_ERROR);
}
}
Aggregations