mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-03-22 06:50:54 +07:00
IDEA-333736: Fix tty size for WSL
The problem: https://github.com/microsoft/WSL/issues/10701 When stdout/err are redirected, WSL reports tty size as 1x1 which breaks `ps` tool (famous "expect trouble" message) that some people might have in profile. `ttyfix` explicitly sets tty size and inserted by `WslDistribution`. Tiny refactoring moved `getToolPath` to reuse it Merge-request: KT-MR-12821 Merged-by: Ilya Kazakevich <ilya.kazakevich@jetbrains.com> GitOrigin-RevId: f33a906b139d22ecdaf0f1b0616ecaaf7bebdd16
This commit is contained in:
committed by
intellij-monorepo-bot
parent
de204fe198
commit
44be55aeee
BIN
bin/win/aarch64/ttyfix
Normal file
BIN
bin/win/aarch64/ttyfix
Normal file
Binary file not shown.
BIN
bin/win/amd64/ttyfix
Normal file
BIN
bin/win/amd64/ttyfix
Normal file
Binary file not shown.
@@ -10,7 +10,7 @@ CFLAGS = -Wall -Wextra -pedantic -Werror -Os -D_POSIX_SOURCE=1 -D_BSD_SOURCE=1
|
||||
LDFLAGS = -static
|
||||
CC = $(MUSL_CC)
|
||||
|
||||
all: $(MUSL_CC) wslproxy wslhash
|
||||
all: $(MUSL_CC) wslproxy wslhash ttyfix
|
||||
|
||||
$(MUSL_DISTR):
|
||||
@echo I will now download musl. If it fails, check you have wget and see README
|
||||
@@ -21,9 +21,10 @@ $(MUSL_CC): $(MUSL_DISTR)
|
||||
cd $(MUSL_DISTR) && ./configure --prefix=$(MUSL_HOME) --syslibdir=$(MUSL_HOME)/lib && $(MAKE) && $(MAKE) install
|
||||
|
||||
wslproxy: wslproxy.c | $(MUSL_CC)
|
||||
ttyfix: ttyfix.c | $(MUSL_CC)
|
||||
wslhash: wslhash.c xxhash.h xxhash.c | $(MUSL_CC)
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
clean:
|
||||
$(RM) wslproxy wslhash
|
||||
$(RM) wslproxy wslhash ttyfix
|
||||
|
||||
@@ -17,4 +17,4 @@ $(MUSL_CROSS_DISTR):
|
||||
.PHONY: all clean
|
||||
|
||||
clean:
|
||||
$(RM) wslproxy wslhash
|
||||
$(RM) wslproxy wslhash ttyfix
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
This project creates two tools:
|
||||
This project creates three tools:
|
||||
|
||||
wslproxy (see wslproxy.svg)
|
||||
To avoid connecting from WSL to Windows (such connections may be blocked by firewall) we connect from Windows to WSL instead.
|
||||
@@ -12,6 +12,9 @@ and also it may be slow: access from WSL to Windows takes a lot of time.
|
||||
This tool runs on WSL only, so it is fast. See WslSync.kt
|
||||
It also reports symbolic links
|
||||
|
||||
ttyfix
|
||||
Sets tty size to workaround https://github.com/microsoft/WSL/issues/10701
|
||||
|
||||
To build tool use Makefile. We link it statically because WSL may lack glibc. Kernel ABI is backward compatible, so use some old Linux
|
||||
|
||||
We use musl libc: https://musl.libc.org/
|
||||
|
||||
29
native/WslTools/ttyfix.c
Normal file
29
native/WslTools/ttyfix.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#include <fcntl.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
|
||||
// Workaround for https://github.com/microsoft/WSL/issues/10701
|
||||
// Provide command to execute along with args. Command will see 100x100 terminal
|
||||
int main(int argc, char *argv[], char *envp[]) {
|
||||
if (argc < 2) {
|
||||
fprintf(stderr, "No command provided");
|
||||
return -1;
|
||||
}
|
||||
struct winsize w;
|
||||
|
||||
int fd = open(ctermid(NULL), O_RDWR);
|
||||
if (fd != -1) { //No terminal, ignore
|
||||
|
||||
const int size_ok = (ioctl(fd, TIOCGWINSZ, &w) == 0 && w.ws_col > 10 && w.ws_row > 10);
|
||||
if (!size_ok) {
|
||||
w.ws_col = 100;
|
||||
w.ws_row = 100;
|
||||
ioctl(fd, TIOCSWINSZ, &w); // Set window size
|
||||
}
|
||||
close(fd);
|
||||
}
|
||||
|
||||
return execve(argv[1], argv + 1, envp); // Substitute self with provided command
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package com.intellij.execution.wsl
|
||||
|
||||
import com.intellij.execution.ExecutionException
|
||||
import com.intellij.execution.configurations.GeneralCommandLine
|
||||
import com.intellij.openapi.application.PathManager
|
||||
import com.intellij.openapi.project.Project
|
||||
import com.intellij.openapi.util.NlsSafe
|
||||
import org.jetbrains.annotations.ApiStatus
|
||||
@@ -57,4 +58,16 @@ interface AbstractWslDistribution {
|
||||
@get:NlsSafe
|
||||
val msId: String
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* throws exception instead of null
|
||||
*/
|
||||
fun AbstractWslDistribution.getWslPathSafe(path: Path): String =
|
||||
getWslPath(path) ?: throw Exception("Can't access from Linux: $path")
|
||||
|
||||
/**
|
||||
* How Linux can access tool from IJ "bin" folder
|
||||
*/
|
||||
fun AbstractWslDistribution.getToolLinuxPath(toolName: String): String =
|
||||
getWslPathSafe(PathManager.findBinFileWithException(toolName))
|
||||
@@ -334,10 +334,13 @@ public class WSLDistribution implements AbstractWslDistribution {
|
||||
}
|
||||
|
||||
if (options.isExecuteCommandInDefaultShell()) {
|
||||
fixTTYSize(commandLine);
|
||||
commandLine.addParameters(SHELL_PARAMETER, "-c", linuxCommandStr);
|
||||
}
|
||||
else {
|
||||
commandLine.addParameters(EXEC_PARAMETER, getShellPath());
|
||||
commandLine.addParameter(EXEC_PARAMETER);
|
||||
fixTTYSize(commandLine);
|
||||
commandLine.addParameter(getShellPath());
|
||||
if (options.isExecuteCommandInInteractiveShell()) {
|
||||
commandLine.addParameters("-i");
|
||||
}
|
||||
@@ -368,6 +371,20 @@ public class WSLDistribution implements AbstractWslDistribution {
|
||||
return commandLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* Workaround for <a href="https://github.com/microsoft/WSL/issues/10701">wrong tty size WSL problem</a>
|
||||
*/
|
||||
private void fixTTYSize(@NotNull GeneralCommandLine cmd) {
|
||||
if (!WslDistributionDescriptor.isCalculatingMountRootCommand(cmd)
|
||||
// Even though mount root is calculated with `options.isExecuteCommandInShell()=false`,
|
||||
// let's protect from possible infinite recursion.
|
||||
&& !(cmd instanceof PtyCommandLine) // PTY command line has correct tty size
|
||||
&& Registry.is("wsl.fix.initial.tty.size.when.running.without.tty", true)) {
|
||||
var ttyfix = AbstractWslDistributionKt.getToolLinuxPath(this, "ttyfix");
|
||||
cmd.addParameter(ttyfix);
|
||||
}
|
||||
}
|
||||
|
||||
private void logCommandLineBefore(@NotNull GeneralCommandLine commandLine, @NotNull WSLCommandLineOptions options) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("[" + getId() + "] " +
|
||||
|
||||
@@ -12,6 +12,7 @@ import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.ProgressManager;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.util.ClearableLazyValue;
|
||||
import com.intellij.openapi.util.Key;
|
||||
import com.intellij.openapi.util.NlsSafe;
|
||||
import com.intellij.openapi.util.io.OSAgnosticPathUtil;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
@@ -37,6 +38,8 @@ import static com.intellij.execution.wsl.WSLUtil.LOG;
|
||||
final class WslDistributionDescriptor {
|
||||
private static final int PROBE_TIMEOUT = SystemProperties.getIntProperty("ide.wsl.probe.timeout", 60_000);
|
||||
|
||||
private static final Key<Boolean> CALCULATING_MOUNT_ROOT_COMMAND = new Key<>("CalculatingMountRootCommand");
|
||||
|
||||
@Tag("id")
|
||||
private @NlsSafe String myId;
|
||||
@Tag("microsoft-id")
|
||||
@@ -145,6 +148,8 @@ final class WslDistributionDescriptor {
|
||||
|
||||
WSLCommandLineOptions options = new WSLCommandLineOptions().setLaunchWithWslExe(true).setExecuteCommandInShell(false);
|
||||
GeneralCommandLine commandLine = new GeneralCommandLine("pwd");
|
||||
// Required to prevent recursion
|
||||
commandLine.putUserData(CALCULATING_MOUNT_ROOT_COMMAND, true);
|
||||
// Use interoperability between Windows and Linux - the Linux process inherits the Windows working directory.
|
||||
commandLine.setWorkDirectory(windowsWorkingDirectory);
|
||||
String linuxWorkingDirectory = readWslOutputLine(options, commandLine, pi);
|
||||
@@ -208,6 +213,14 @@ final class WslDistributionDescriptor {
|
||||
return output.getStdoutLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* Command line is used to calculate mount root
|
||||
*/
|
||||
static boolean isCalculatingMountRootCommand(@NotNull GeneralCommandLine commandLine) {
|
||||
Boolean data = commandLine.getUserData(CALCULATING_MOUNT_ROOT_COMMAND);
|
||||
return data != null && data;
|
||||
}
|
||||
|
||||
private static <T> T executeOrRunTask(@NotNull Function<? super @Nullable ProgressIndicator, ? extends T> commandRunner) {
|
||||
if (!ApplicationManager.getApplication().isDispatchThread()) {
|
||||
return commandRunner.apply(null);
|
||||
|
||||
@@ -158,6 +158,10 @@
|
||||
description="Use 'wsl.exe -l -v' to get distribution list. If it's disabled 'wsl.exe -l -q' will be used."/>
|
||||
<registryKey key="wsl.use.utf8.encoding" os="windows" defaultValue="true" restartRequired="false"
|
||||
description="Use UTF-8 as default encoding for all WSL distributions, otherwise default console encoding will be used (see Preferences | Editor | General | Console )"/>
|
||||
<registryKey key="wsl.fix.initial.tty.size.when.running.without.tty"
|
||||
restartRequired="false"
|
||||
description="Set initial Linux tty size to 100x100 for WSL processes not attached to Windows PTY (workaround for https://github.com/microsoft/WSL/issues/10701)"
|
||||
defaultValue="true"/>
|
||||
<applicationService serviceInterface="com.intellij.execution.wsl.WslDistributionManager"
|
||||
serviceImplementation="com.intellij.execution.wsl.WslDistributionManagerImpl"/>
|
||||
<executionTargetType implementation="com.intellij.execution.wsl.target.WslTargetType"/>
|
||||
|
||||
@@ -2,20 +2,6 @@ package com.intellij.execution.wsl
|
||||
|
||||
import com.intellij.execution.configurations.GeneralCommandLine
|
||||
import com.intellij.execution.processTools.ProcessExistedNotZeroException
|
||||
import com.intellij.openapi.application.PathManager
|
||||
import java.nio.file.Path
|
||||
|
||||
/**
|
||||
* throws exception instead of null
|
||||
*/
|
||||
internal fun AbstractWslDistribution.getWslPathSafe(path: Path): String = getWslPath(path)
|
||||
?: throw Exception("Can't access from Linux: $path")
|
||||
|
||||
/**
|
||||
* How Linux can access tool from IJ "bin" folder
|
||||
*/
|
||||
internal fun AbstractWslDistribution.getToolLinuxPath(toolName: String): String =
|
||||
getWslPathSafe(PathManager.findBinFileWithException(toolName))
|
||||
|
||||
internal fun AbstractWslDistribution.getTool(toolName: String, vararg arguments: String): GeneralCommandLine {
|
||||
val toolOnLinux = getToolLinuxPath(toolName)
|
||||
|
||||
Reference in New Issue
Block a user