Skip to content

Commit 9c6565a

Browse files
authored
Use scoped process handler in BlazeCommandGenericRunConfigurationRunner (#7691)
Revert to previous behaviour of using the ScopedProcess Handler in the BlazeCommandGenericRunConfigurationRunner and remove support for the generic process handler. FYI, the entire logic with BuildResultHelperBep and LocalBuildEventProtocolTestFinderStrategy is pretty messy. The result helper is closed before the strategy is executed, causing all the 'could not delete BEP file' warnings. This needs a proper refactor later. fixes #7648 #7623
1 parent 7620231 commit 9c6565a

File tree

2 files changed

+54
-167
lines changed

2 files changed

+54
-167
lines changed

base/src/com/google/idea/blaze/base/run/confighandler/BlazeCommandGenericRunConfigurationRunner.java

Lines changed: 52 additions & 167 deletions
Original file line numberDiff line numberDiff line change
@@ -15,22 +15,15 @@
1515
*/
1616
package com.google.idea.blaze.base.run.confighandler;
1717

18-
import static com.google.common.base.Verify.verify;
19-
2018
import com.google.common.base.Preconditions;
2119
import com.google.common.collect.ImmutableList;
22-
import com.google.common.util.concurrent.FutureCallback;
23-
import com.google.common.util.concurrent.Futures;
24-
import com.google.common.util.concurrent.ListenableFuture;
25-
import com.google.idea.blaze.base.async.executor.BlazeExecutor;
2620
import com.google.idea.blaze.base.async.process.LineProcessingOutputStream;
2721
import com.google.idea.blaze.base.bazel.BuildSystem.BuildInvoker;
2822
import com.google.idea.blaze.base.command.BlazeCommand;
2923
import com.google.idea.blaze.base.command.BlazeCommandName;
3024
import com.google.idea.blaze.base.command.BlazeFlags;
3125
import com.google.idea.blaze.base.command.BlazeInvocationContext;
32-
import com.google.idea.blaze.base.command.buildresult.BuildResultParser;
33-
import com.google.idea.blaze.base.command.buildresult.bepparser.BuildEventStreamProvider;
26+
import com.google.idea.blaze.base.command.buildresult.BuildResultHelperBep;
3427
import com.google.idea.blaze.base.console.BlazeConsoleLineProcessorProvider;
3528
import com.google.idea.blaze.base.issueparser.ToolWindowTaskIssueOutputFilter;
3629
import com.google.idea.blaze.base.model.primitives.WorkspaceRoot;
@@ -44,9 +37,7 @@
4437
import com.google.idea.blaze.base.run.smrunner.BlazeTestUiSession;
4538
import com.google.idea.blaze.base.run.smrunner.SmRunnerUtils;
4639
import com.google.idea.blaze.base.run.state.BlazeCommandRunConfigurationCommonState;
47-
import com.google.idea.blaze.base.run.testlogs.BlazeTestResultFinderStrategy;
48-
import com.google.idea.blaze.base.run.testlogs.BlazeTestResultHolder;
49-
import com.google.idea.blaze.base.run.testlogs.BlazeTestResults;
40+
import com.google.idea.blaze.base.run.testlogs.LocalBuildEventProtocolTestFinderStrategy;
5041
import com.google.idea.blaze.base.scope.BlazeContext;
5142
import com.google.idea.blaze.base.scope.OutputSink;
5243
import com.google.idea.blaze.base.scope.scopes.IdeaLogScope;
@@ -55,8 +46,6 @@
5546
import com.google.idea.blaze.base.settings.BlazeImportSettings;
5647
import com.google.idea.blaze.base.settings.BlazeImportSettingsManager;
5748
import com.google.idea.blaze.base.settings.BlazeUserSettings;
58-
import com.google.idea.blaze.base.sync.aspects.BlazeBuildOutputs;
59-
import com.google.idea.blaze.common.Interners;
6049
import com.google.idea.blaze.common.PrintOutput;
6150
import com.google.idea.blaze.common.PrintOutput.OutputType;
6251
import com.intellij.execution.DefaultExecutionResult;
@@ -70,22 +59,16 @@
7059
import com.intellij.execution.filters.Filter;
7160
import com.intellij.execution.filters.TextConsoleBuilderImpl;
7261
import com.intellij.execution.filters.UrlFilter;
73-
import com.intellij.execution.process.ProcessAdapter;
74-
import com.intellij.execution.process.ProcessEvent;
7562
import com.intellij.execution.process.ProcessHandler;
7663
import com.intellij.execution.process.ProcessListener;
7764
import com.intellij.execution.runners.ExecutionEnvironment;
7865
import com.intellij.execution.runners.ProgramRunner;
7966
import com.intellij.execution.ui.ConsoleView;
8067
import com.intellij.execution.ui.ConsoleViewContentType;
81-
import com.intellij.openapi.application.ApplicationManager;
8268
import com.intellij.openapi.project.Project;
83-
import java.io.OutputStream;
8469
import java.util.ArrayList;
8570
import java.util.List;
8671
import java.util.Map;
87-
import org.jetbrains.annotations.NotNull;
88-
import org.jetbrains.annotations.Nullable;
8972

9073
/**
9174
* Generic runner for {@link BlazeCommandRunConfiguration}s, used as a fallback in the case where no
@@ -107,6 +90,7 @@ public boolean executeBeforeRunTask(ExecutionEnvironment environment) {
10790

10891
/** {@link RunProfileState} for generic blaze commands. */
10992
public static class BlazeCommandRunProfileState extends CommandLineState {
93+
11094
private static final int BLAZE_BUILD_INTERRUPTED = 8;
11195
private final BlazeCommandRunConfiguration configuration;
11296
private final BlazeCommandRunConfigurationCommonState handlerState;
@@ -148,8 +132,8 @@ protected ProcessHandler startProcess() throws ExecutionException {
148132
ProjectViewSet projectViewSet = ProjectViewManager.getInstance(project).getProjectViewSet();
149133
assert projectViewSet != null;
150134
BlazeContext context = BlazeContext.create();
151-
BuildInvoker invoker =
152-
Blaze.getBuildSystemProvider(project).getBuildSystem().getBuildInvoker(project);
135+
BuildInvoker invoker = Blaze.getBuildSystemProvider(project).getBuildSystem().getBuildInvoker(project);
136+
WorkspaceRoot workspaceRoot = WorkspaceRoot.fromImportSettings(importSettings);
153137
BlazeCommand.Builder blazeCommand =
154138
getBlazeCommand(
155139
project,
@@ -158,109 +142,67 @@ protected ProcessHandler startProcess() throws ExecutionException {
158142
ImmutableList.of(),
159143
context);
160144
return isTest()
161-
? getProcessHandlerForTests(project, invoker, blazeCommand, context)
162-
: getProcessHandlerForNonTests(project, invoker, blazeCommand, context);
163-
}
164-
165-
private ProcessHandler getGenericProcessHandler() {
166-
return new ProcessHandler() {
167-
@Override
168-
protected void destroyProcessImpl() {
169-
notifyProcessTerminated(BLAZE_BUILD_INTERRUPTED);
170-
}
171-
172-
@Override
173-
protected void detachProcessImpl() {
174-
ApplicationManager.getApplication().executeOnPooledThread(this::notifyProcessDetached);
175-
}
176-
177-
@Override
178-
public boolean detachIsDefault() {
179-
return false;
180-
}
181-
182-
@Nullable
183-
@Override
184-
public OutputStream getProcessInput() {
185-
return null;
186-
}
187-
};
145+
? getProcessHandlerForTests(project, blazeCommand, workspaceRoot, context)
146+
: getScopedProcessHandler(project, blazeCommand.build(), workspaceRoot);
188147
}
189148

190-
private ProcessHandler getProcessHandlerForNonTests(
149+
private ProcessHandler getScopedProcessHandler(
191150
Project project,
192-
BuildInvoker invoker,
193-
BlazeCommand.Builder blazeCommandBuilder,
194-
BlazeContext context)
151+
BlazeCommand blazeCommand,
152+
WorkspaceRoot workspaceRoot
153+
)
195154
throws ExecutionException {
196-
ProcessHandler processHandler = getGenericProcessHandler();
197-
ConsoleView consoleView = getConsoleBuilder().getConsole();
198-
context.addOutputSink(PrintOutput.class, new WritingOutputSink(consoleView));
199-
setConsoleBuilder(
200-
new TextConsoleBuilderImpl(project) {
201-
@Override
202-
protected ConsoleView createConsole() {
203-
return consoleView;
204-
}
205-
});
206-
addConsoleFilters(consoleFilters.toArray(new Filter[0]));
207-
208-
@NotNull Map<String, String> envVars = handlerState.getUserEnvVarsState().getData().getEnvs();
209-
ListenableFuture<BlazeBuildOutputs> blazeBuildOutputsListenableFuture =
210-
BlazeExecutor.getInstance()
211-
.submit(
212-
() -> {
213-
try (BuildEventStreamProvider streamProvider =
214-
invoker.invoke(blazeCommandBuilder, context)) {
215-
return BlazeBuildOutputs.fromParsedBepOutput(
216-
BuildResultParser.getBuildOutput(streamProvider, Interners.STRING));
217-
}
218-
});
219-
Futures.addCallback(
220-
blazeBuildOutputsListenableFuture,
221-
new FutureCallback<BlazeBuildOutputs>() {
222-
@Override
223-
public void onSuccess(BlazeBuildOutputs blazeBuildOutputs) {
224-
processHandler.detachProcess();
225-
}
226-
155+
GeneralCommandLine commandLine = new GeneralCommandLine(blazeCommand.toList());
156+
EnvironmentVariablesData envVarState = handlerState.getUserEnvVarsState().getData();
157+
commandLine.withEnvironment(envVarState.getEnvs());
158+
commandLine.withParentEnvironmentType(
159+
envVarState.isPassParentEnvs()
160+
? GeneralCommandLine.ParentEnvironmentType.CONSOLE
161+
: GeneralCommandLine.ParentEnvironmentType.NONE);
162+
return new ScopedBlazeProcessHandler(
163+
project,
164+
commandLine,
165+
workspaceRoot,
166+
new ScopedBlazeProcessHandler.ScopedProcessHandlerDelegate() {
227167
@Override
228-
public void onFailure(Throwable throwable) {
229-
context.handleException(throwable.getMessage(), throwable);
230-
processHandler.detachProcess();
168+
public void onBlazeContextStart(BlazeContext context) {
169+
context
170+
.push(
171+
new ProblemsViewScope(
172+
project, BlazeUserSettings.getInstance().getShowProblemsViewOnRun()))
173+
.push(new IdeaLogScope());
231174
}
232-
},
233-
BlazeExecutor.getInstance().getExecutor());
234175

235-
processHandler.addProcessListener(
236-
new ProcessAdapter() {
237176
@Override
238-
public void processWillTerminate(@NotNull ProcessEvent event, boolean willBeDestroyed) {
239-
if (willBeDestroyed) {
240-
context.setCancelled();
241-
}
177+
public ImmutableList<ProcessListener> createProcessListeners(BlazeContext context) {
178+
LineProcessingOutputStream outputStream =
179+
LineProcessingOutputStream.of(
180+
BlazeConsoleLineProcessorProvider.getAllStderrLineProcessors(context));
181+
return ImmutableList.of(new LineProcessingProcessAdapter(outputStream));
242182
}
243183
});
244-
return processHandler;
245184
}
246185

247186
private ProcessHandler getProcessHandlerForTests(
248187
Project project,
249-
BuildInvoker invoker,
250188
BlazeCommand.Builder blazeCommandBuilder,
251-
BlazeContext context) {
252-
BlazeTestResultFinderStrategy testResultFinderStrategy = new BlazeTestResultHolder();
253-
BlazeTestUiSession testUiSession = null;
189+
WorkspaceRoot workspaceRoot,
190+
BlazeContext context
191+
) throws ExecutionException {
192+
// TODO: find proper place to close the result helper (same for BlazeCidrLauncher)
193+
final var buildResultHelper = new BuildResultHelperBep();
194+
final var testResultFinderStrategy = new LocalBuildEventProtocolTestFinderStrategy(buildResultHelper.getOutputFile());
195+
254196
if (BlazeTestEventsHandler.targetsSupported(project, configuration.getTargets())) {
255-
testUiSession =
197+
final var testUiSession =
256198
BlazeTestUiSession.create(
257199
ImmutableList.<String>builder()
258200
.add("--runs_per_test=1")
259201
.add("--flaky_test_attempts=1")
202+
.addAll(buildResultHelper.getBuildFlags())
260203
.build(),
261204
testResultFinderStrategy);
262-
}
263-
if (testUiSession != null) {
205+
264206
ConsoleView consoleView =
265207
SmRunnerUtils.getConsoleView(
266208
project, configuration, getEnvironment().getExecutor(), testUiSession);
@@ -272,76 +214,19 @@ protected ConsoleView createConsole() {
272214
}
273215
});
274216
context.addOutputSink(PrintOutput.class, new WritingOutputSink(consoleView));
275-
}
276-
addConsoleFilters(consoleFilters.toArray(new Filter[0]));
277-
@NotNull Map<String, String> envVars = handlerState.getUserEnvVarsState().getData().getEnvs();
278217

279-
if (invoker.getCommandRunner().canUseCli()) {
280-
// If we can use the CLI, that means we will run through Bazel (as opposed to a raw process handler)
281-
// When running `bazel test`, bazel will not forward the environment to the tests themselves -- we need to use
282-
// the --test_env flag for that. Therefore, we convert all the env vars to --test_env flags here.
283-
for (Map.Entry<String, String> env: envVars.entrySet()) {
284-
blazeCommandBuilder.addBlazeFlags(BlazeFlags.TEST_ENV, String.format("%s=%s", env.getKey(), env.getValue()));
285-
}
218+
blazeCommandBuilder.addBlazeFlags(testUiSession.getBlazeFlags());
286219
}
287-
return getCommandRunnerProcessHandlerForTests(
288-
invoker, blazeCommandBuilder, testResultFinderStrategy, context);
289-
}
290220

291-
private ProcessHandler getCommandRunnerProcessHandlerForTests(
292-
BuildInvoker invoker,
293-
BlazeCommand.Builder blazeCommandBuilder,
294-
BlazeTestResultFinderStrategy testResultFinderStrategy,
295-
BlazeContext context) {
296-
ProcessHandler processHandler = getGenericProcessHandler();
297-
@NotNull Map<String, String> envVars = handlerState.getUserEnvVarsState().getData().getEnvs();
298-
ListenableFuture<BlazeTestResults> blazeTestResultsFuture =
299-
BlazeExecutor.getInstance()
300-
.submit(
301-
() -> {
302-
try (BuildEventStreamProvider streamProvider =
303-
invoker.invoke(blazeCommandBuilder, context)) {
304-
return BuildResultParser.getTestResults(streamProvider);
305-
}
306-
});
307-
Futures.addCallback(
308-
blazeTestResultsFuture,
309-
new FutureCallback<BlazeTestResults>() {
310-
@Override
311-
public void onSuccess(BlazeTestResults blazeTestResults) {
312-
// The command-runners allow using a remote BES for parsing the test results, so we
313-
// use a BlazeTestResultHolder to store the test results for the IDE to find/read
314-
// later. The LocalTestResultFinderStrategy won't work here since it writes/reads the
315-
// test results to a local file.
316-
verify(testResultFinderStrategy instanceof BlazeTestResultHolder);
317-
((BlazeTestResultHolder) testResultFinderStrategy).setTestResults(blazeTestResults);
318-
processHandler.detachProcess();
319-
}
221+
addConsoleFilters(consoleFilters.toArray(new Filter[0]));
320222

321-
@Override
322-
public void onFailure(Throwable throwable) {
323-
context.handleException(throwable.getMessage(), throwable);
324-
verify(testResultFinderStrategy instanceof BlazeTestResultHolder);
325-
((BlazeTestResultHolder) testResultFinderStrategy)
326-
.setTestResults(BlazeTestResults.NO_RESULTS);
327-
processHandler.detachProcess();
328-
}
329-
},
330-
BlazeExecutor.getInstance().getExecutor());
223+
// When running `bazel test`, bazel will not forward the environment to the tests themselves -- we need to use
224+
// the --test_env flag for that. Therefore, we convert all the env vars to --test_env flags here.
225+
for (Map.Entry<String, String> env : handlerState.getUserEnvVarsState().getData().getEnvs().entrySet()) {
226+
blazeCommandBuilder.addBlazeFlags(BlazeFlags.TEST_ENV, String.format("%s=%s", env.getKey(), env.getValue()));
227+
}
331228

332-
processHandler.addProcessListener(
333-
new ProcessAdapter() {
334-
@Override
335-
public void processWillTerminate(@NotNull ProcessEvent event, boolean willBeDestroyed) {
336-
if (willBeDestroyed) {
337-
context.setCancelled();
338-
verify(testResultFinderStrategy instanceof BlazeTestResultHolder);
339-
((BlazeTestResultHolder) testResultFinderStrategy)
340-
.setTestResults(BlazeTestResults.NO_RESULTS);
341-
}
342-
}
343-
});
344-
return processHandler;
229+
return getScopedProcessHandler(project, blazeCommandBuilder.build(), workspaceRoot);
345230
}
346231

347232
private BlazeCommand.Builder getBlazeCommand(

clwb/src/com/google/idea/blaze/clwb/run/BlazeCidrLauncher.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,8 @@ private ProcessHandler createProcess(CommandLineState state, List<String> extraB
118118
BlazeTestUiSession testUiSession = null;
119119
if (useTestUi()
120120
&& BlazeTestEventsHandler.targetsSupported(project, configuration.getTargets())) {
121+
122+
// TODO: the result helper is closed before the command is executed, this is useless
121123
try (BuildResultHelper buildResultHelper = invoker.createBuildResultHelper()) {
122124
if (!(buildResultHelper instanceof BuildResultHelperBep)) {
123125
throw new ExecutionException("Build result helper not supported");

0 commit comments

Comments
 (0)