use wslproxy for wsl builds connectivity (IDEA-338992)

GitOrigin-RevId: 4c88373873732b6ca0e7d11b97f0aee0431ae138
This commit is contained in:
Eugene Zhuravlev
2024-05-02 16:12:31 +00:00
committed by intellij-monorepo-bot
parent a91721ab95
commit 9a359dc3dd
6 changed files with 84 additions and 85 deletions
@@ -8,13 +8,11 @@
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="intellij.java.compiler" exported="" />
<orderEntry type="library" name="OroMatcher" level="project" />
<orderEntry type="module" module-name="intellij.platform.util.jdom" />
<orderEntry type="module" module-name="intellij.platform.util" />
<orderEntry type="module" module-name="intellij.java" />
<orderEntry type="module" module-name="intellij.java.rt" />
<orderEntry type="module" module-name="intellij.java.compiler.instrumentationUtil" />
<orderEntry type="library" name="ASM" level="project" />
<orderEntry type="module" module-name="intellij.platform.ide" />
<orderEntry type="module" module-name="intellij.platform.lang.impl" />
<orderEntry type="module" module-name="intellij.jsp" />
@@ -25,30 +23,33 @@
<orderEntry type="module" module-name="intellij.platform.jps.model.impl" />
<orderEntry type="module" module-name="intellij.java.analysis.impl" />
<orderEntry type="module" module-name="intellij.platform.builtInServer.impl" />
<orderEntry type="library" name="kotlin-stdlib" level="project" />
<orderEntry type="library" name="protobuf" level="project" />
<orderEntry type="library" name="netty-codec-http" level="project" />
<orderEntry type="module" module-name="intellij.platform.vcs.impl" />
<orderEntry type="module" module-name="intellij.platform.externalSystem" />
<orderEntry type="library" name="StreamEx" level="project" />
<orderEntry type="module" module-name="intellij.platform.statistics" />
<orderEntry type="library" name="fastutil-min" level="project" />
<orderEntry type="library" name="jps-javac-extension" level="project" />
<orderEntry type="library" name="netty-buffer" level="project" />
<orderEntry type="module" module-name="intellij.platform.core.ui" />
<orderEntry type="module" module-name="intellij.platform.workspace.jps" />
<orderEntry type="module" module-name="intellij.platform.ide.util.io.impl" />
<orderEntry type="module" module-name="intellij.platform.ide.util.netty" />
<orderEntry type="module" module-name="intellij.platform.wsl.impl" />
<orderEntry type="module" module-name="intellij.platform.backend.workspace" />
<orderEntry type="module" module-name="intellij.platform.tracing.rt" />
<orderEntry type="module" module-name="intellij.platform.diagnostic.telemetry" />
<orderEntry type="library" name="OroMatcher" level="project" />
<orderEntry type="library" name="ASM" level="project" />
<orderEntry type="library" name="kotlin-stdlib" level="project" />
<orderEntry type="library" name="protobuf" level="project" />
<orderEntry type="library" name="netty-codec-http" level="project" />
<orderEntry type="library" name="StreamEx" level="project" />
<orderEntry type="library" name="fastutil-min" level="project" />
<orderEntry type="library" name="jps-javac-extension" level="project" />
<orderEntry type="library" name="netty-buffer" level="project" />
<orderEntry type="library" name="winp" level="project" />
<orderEntry type="library" name="jackson" level="project" />
<orderEntry type="library" name="jackson-databind" level="project" />
<orderEntry type="library" name="kotlinx-coroutines-core" level="project" />
<orderEntry type="module" module-name="intellij.platform.backend.workspace" />
<orderEntry type="library" name="caffeine" level="project" />
<orderEntry type="library" name="opentelemetry" level="project" />
<orderEntry type="library" name="opentelemetry-semconv" level="project" />
<orderEntry type="module" module-name="intellij.platform.diagnostic.telemetry" />
<orderEntry type="library" name="kotlinx-collections-immutable" level="project" />
</component>
<component name="copyright">
@@ -124,11 +124,9 @@ public final class CompileDriver {
buildManager.postponeBackgroundTasks();
buildManager.cancelAutoMakeTasks(myProject);
TaskFuture<?> future = compileInExternalProcess(compileContext, true);
if (future != null) {
while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) {
if (indicator.isCanceled()) {
future.cancel(false);
}
while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) {
if (indicator.isCanceled()) {
future.cancel(false);
}
}
}
@@ -221,7 +219,7 @@ public final class CompileDriver {
return scopes;
}
@Nullable
@NotNull
private TaskFuture<?> compileInExternalProcess(@NotNull final CompileContextImpl compileContext, final boolean onlyCheckUpToDate) {
final CompileScope scope = compileContext.getCompileScope();
final Collection<String> paths = ReadAction.compute(() -> CompileScopeUtil.fetchFiles(compileContext));
@@ -450,21 +448,19 @@ public final class CompileDriver {
}
TaskFuture<?> future = compileInExternalProcess(compileContext, false);
if (future != null) {
Tracer.Span compileInExternalProcessSpan = Tracer.start("compile in external process");
while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) {
if (indicator.isCanceled()) {
future.cancel(false);
}
}
compileInExternalProcessSpan.complete();
if (!executeCompileTasks(compileContext, false)) {
COMPILE_SERVER_BUILD_STATUS.set(compileContext, ExitStatus.CANCELLED);
}
if (compileContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
COMPILE_SERVER_BUILD_STATUS.set(compileContext, ExitStatus.ERRORS);
Tracer.Span compileInExternalProcessSpan = Tracer.start("compile in external process");
while (!future.waitFor(200L, TimeUnit.MILLISECONDS)) {
if (indicator.isCanceled()) {
future.cancel(false);
}
}
compileInExternalProcessSpan.complete();
if (!executeCompileTasks(compileContext, false)) {
COMPILE_SERVER_BUILD_STATUS.set(compileContext, ExitStatus.CANCELLED);
}
if (compileContext.getMessageCount(CompilerMessageCategory.ERROR) > 0) {
COMPILE_SERVER_BUILD_STATUS.set(compileContext, ExitStatus.ERRORS);
}
}
catch (ProcessCanceledException ignored) {
compileContext.putUserDataIfAbsent(COMPILE_SERVER_BUILD_STATUS, ExitStatus.CANCELLED);
@@ -1,4 +1,4 @@
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.compiler.server;
import com.intellij.compiler.YourKitProfilerService;
@@ -6,7 +6,6 @@ import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import org.jetbrains.annotations.NotNull;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.List;
@@ -27,11 +26,6 @@ interface BuildCommandLineBuilder {
@NotNull
Path getHostWorkingDirectory();
InetAddress getListenAddress();
@NotNull
String getHostIp() throws ExecutionException;
String getYjpAgentPath(YourKitProfilerService yourKitProfilerService);
void setCharset(Charset charset);
@@ -23,6 +23,7 @@ import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.wsl.WSLDistribution;
import com.intellij.execution.wsl.WslDistributionManager;
import com.intellij.execution.wsl.WslPath;
import com.intellij.execution.wsl.WslProxy;
import com.intellij.ide.IdleTracker;
import com.intellij.ide.PowerSaveMode;
import com.intellij.ide.actions.RevealFileAction;
@@ -287,6 +288,7 @@ public final class BuildManager implements Disposable {
}
private final List<ListeningConnection> myListeningConnections = new ArrayList<>();
private final Map<String, WslProxy> myWslProxyCache = new HashMap<>();
private final @NotNull Charset mySystemCharset = CharsetToolkit.getDefaultSystemCharset();
private volatile boolean myBuildProcessDebuggingEnabled;
@@ -406,7 +408,10 @@ public final class BuildManager implements Disposable {
});
}
ShutDownTracker.getInstance().registerShutdownTask(this::stopListening);
ShutDownTracker.getInstance().registerShutdownTask(() -> {
stopListening();
clearWslProxyCache();
});
if (!IS_UNIT_TEST_MODE) {
ScheduledFuture<?> future = AppExecutorUtil.getAppScheduledExecutorService().scheduleWithFixedDelay(() -> runCommand(myGCTask), 3, 180, TimeUnit.MINUTES);
@@ -716,10 +721,8 @@ public final class BuildManager implements Disposable {
final TaskFuture<?> future = scheduleBuild(
project, false, true, false, scopes, Collections.emptyList(), Collections.singletonMap(BuildParametersKeys.IS_AUTOMAKE, "true"), handler
);
if (future != null) {
myAutomakeFutures.put(future, project);
futures.add(new Pair<>(future, handler));
}
myAutomakeFutures.put(future, project);
futures.add(new Pair<>(future, handler));
}
boolean needAdditionalBuild = false;
for (Pair<TaskFuture<?>, AutoMakeMessageHandler> pair : futures) {
@@ -862,7 +865,7 @@ public final class BuildManager implements Disposable {
return result != null && !result.first.isDone()? result : null;
}
public @Nullable TaskFuture<?> scheduleBuild(
public @NotNull TaskFuture<?> scheduleBuild(
final Project project, final boolean isRebuild, final boolean isMake,
final boolean onlyCheckUpToDate, final List<TargetTypeBuildScope> scopes,
final Collection<String> paths,
@@ -873,15 +876,6 @@ public final class BuildManager implements Disposable {
final boolean isAutomake = messageHandler instanceof AutoMakeMessageHandler;
final WSLDistribution wslDistribution = findWSLDistribution(project);
final BuilderMessageHandler handler = new NotifyingMessageHandler(project, messageHandler, wslDistribution != null ? wslDistribution::getWindowsPath : null, isAutomake);
try {
ensureListening(wslDistribution != null ? wslDistribution.getHostIpAddress() : InetAddress.getLoopbackAddress());
}
catch (Exception e) {
final UUID sessionId = UUID.randomUUID(); // the actual session did not start; use random UUID
handler.handleFailure(sessionId, CmdlineProtoUtil.createFailure(e.getMessage(), null));
handler.sessionTerminated(sessionId);
return null;
}
Function<String, String> pathMapper = wslDistribution != null ? wslDistribution::getWslPath : Function.identity();
final DelegateFuture _future = new DelegateFuture();
@@ -1128,9 +1122,30 @@ public final class BuildManager implements Disposable {
return startListening(inetAddress);
}
private synchronized int getWslPort(WSLDistribution dist, int localPort) {
return myWslProxyCache.computeIfAbsent(dist.getId() + ":" + localPort, key -> new WslProxy(dist, localPort)).getWslIngressPort();
}
private synchronized void cleanWslProxies(WSLDistribution dist) {
String idPrefix = dist.getId() + ":";
List<String> keys = new SmartList<>();
for (String key : myWslProxyCache.keySet()) {
if (key.startsWith(idPrefix)) {
keys.add(key);
}
}
for (String key : keys) {
WslProxy proxy = myWslProxyCache.remove(key);
if (proxy != null) {
Disposer.dispose(proxy);
}
}
}
@Override
public void dispose() {
stopListening();
clearWslProxyCache();
myAutomakeTrigger.cancel();
myRequestsProcessor.cancel();
}
@@ -1323,6 +1338,11 @@ public final class BuildManager implements Disposable {
final CompilerConfiguration projectConfig = CompilerConfiguration.getInstance(project);
final CompilerWorkspaceConfiguration config = CompilerWorkspaceConfiguration.getInstance(project);
InetAddress listenAddress = InetAddress.getLoopbackAddress();
int listenPort = ensureListening(listenAddress);
String buildProcessConnectHost = listenAddress.getHostAddress();
int buildProcessConnectPort = listenPort;
BuildCommandLineBuilder cmdLine;
WslPath wslPath = WslPath.parseWindowsUncPath(vmExecutablePath);
if (wslPath != null) {
@@ -1331,6 +1351,8 @@ public final class BuildManager implements Disposable {
throw new ExecutionException(JavaCompilerBundle.message("build.process.wsl.distribution.dont.match", sdkName + " (WSL " + sdkDistribution.getPresentableName() + ")", MINIMUM_REQUIRED_JPS_BUILD_JAVA_VERSION));
}
cmdLine = new WslBuildCommandLineBuilder(project, sdkDistribution, wslPath.getLinuxPath(), progressIndicator);
buildProcessConnectHost = "127.0.0.1"; // WslProxy listen address on linux side
buildProcessConnectPort = getWslPort(sdkDistribution, listenPort);
}
else {
if (projectWslDistribution != null) {
@@ -1338,7 +1360,6 @@ public final class BuildManager implements Disposable {
}
cmdLine = new LocalBuildCommandLineBuilder(vmExecutablePath);
}
int listenPort = ensureListening(cmdLine.getListenAddress());
boolean profileWithYourKit = false;
boolean isAgentpathSet = false;
@@ -1612,8 +1633,8 @@ public final class BuildManager implements Disposable {
}
cmdLine.addParameter(BuildMain.class.getName());
cmdLine.addParameter(cmdLine.getHostIp());
cmdLine.addParameter(Integer.toString(listenPort));
cmdLine.addParameter(buildProcessConnectHost);
cmdLine.addParameter(Integer.toString(buildProcessConnectPort));
cmdLine.addParameter(sessionId.toString());
cmdLine.addParameter(cmdLine.getWorkingDirectory());
@@ -1782,13 +1803,24 @@ public final class BuildManager implements Disposable {
return null;
}
private void stopListening() {
private synchronized void stopListening() {
for (ListeningConnection connection : myListeningConnections) {
connection.myChannelRegistrar.close();
}
myListeningConnections.clear();
}
private synchronized void clearWslProxyCache() {
for (WslProxy proxy : myWslProxyCache.values()) {
try {
Disposer.dispose(proxy);
}
catch (Throwable ignored) {
}
}
myWslProxyCache.clear();
}
private int startListening(InetAddress address) {
ListeningConnection listeningConnection = new ListeningConnection(address);
BuiltInServerManager builtInServerManager = BuiltInServerManager.getInstance();
@@ -2193,6 +2225,10 @@ public final class BuildManager implements Disposable {
}
}
});
WSLDistribution wslDistr = findWSLDistribution(project);
if (wslDistr != null) {
cleanWslProxies(wslDistr);
}
}
@Override
@@ -10,7 +10,6 @@ import com.intellij.openapi.util.io.FileUtilRt;
import org.jetbrains.annotations.NotNull;
import java.io.File;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.nio.file.Path;
import java.util.List;
@@ -62,16 +61,6 @@ final class LocalBuildCommandLineBuilder implements BuildCommandLineBuilder {
return getLocalBuildSystemDirectory();
}
@Override
public InetAddress getListenAddress() {
return InetAddress.getLoopbackAddress();
}
@Override
public @NotNull String getHostIp() {
return getListenAddress().getHostAddress();
}
@Override
public String getYjpAgentPath(YourKitProfilerService yourKitProfilerService) {
return getLocalBuildSystemDirectory()
@@ -20,7 +20,6 @@ import org.jetbrains.jps.api.GlobalOptions;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.InetAddress;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
@@ -43,8 +42,7 @@ final class WslBuildCommandLineBuilder implements BuildCommandLineBuilder {
private static boolean CURRENT_SNAPSHOT_COPIED = false;
private boolean myReportedProgress;
WslBuildCommandLineBuilder(@NotNull Project project, @NotNull WSLDistribution distribution, @NotNull String sdkPath,
@Nullable ProgressIndicator progressIndicator) {
WslBuildCommandLineBuilder(@NotNull Project project, @NotNull WSLDistribution distribution, @NotNull String sdkPath, @Nullable ProgressIndicator progressIndicator) {
myProject = project;
myDistribution = distribution;
myProgressIndicator = progressIndicator;
@@ -156,21 +154,6 @@ final class WslBuildCommandLineBuilder implements BuildCommandLineBuilder {
return myWorkingDirectory;
}
@Override
public InetAddress getListenAddress() {
try {
return myDistribution.getHostIpAddress();
}
catch (ExecutionException ignored) {
return null;
}
}
@Override
public @NotNull String getHostIp() throws ExecutionException {
return myDistribution.getHostIpAddress().getHostAddress();
}
@Override
public String getYjpAgentPath(YourKitProfilerService yourKitProfilerService) {
return myWorkingDirectory + "/" + yourKitProfilerService.getYKAgentFullNameForWSL();