Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Started subprocesses close pipe on win11 #1115

Open
DasBabyPixel opened this issue Nov 27, 2024 · 0 comments
Open

Started subprocesses close pipe on win11 #1115

DasBabyPixel opened this issue Nov 27, 2024 · 0 comments

Comments

@DasBabyPixel
Copy link
Contributor

DasBabyPixel commented Nov 27, 2024

The exec terminal provider seems to start a subprocess in isPosixSystemStream. The ProcessBuilder for that process uses ProcessBuilder.inheritIO(), which seems to close the stdin pipe when the process is finished.
One thing I noticed: This seems to only be a problem on my windows11 machine if the process running jline3 is itself also created by a ProcessBuilder (gradle in my case). If I execute the same problem with the exact same commandline from the windows terminal, everything functions like it should.
This issue does not happen on my windows 10 laptop.

Here are two tests, that demonstrate the problem. To execute them, one must be executed at a time, as unit tests usually have no console input.

    @Test
    void testBreaks() throws IOException, InterruptedException {
        new ProcessBuilder().command("dir").inheritIO().start().waitFor();
        System.in.read();
    }

    @Test
    void testWorks() throws IOException, InterruptedException {
        new ProcessBuilder("dir")
                .redirectOutput(ExecTerminalProvider.newDescriptor(FileDescriptor.out))
                .redirectError(ExecTerminalProvider.newDescriptor(FileDescriptor.err))
                .start()
                .waitFor();
        System.in.read();
    }

testBreaks:

java.io.IOException: The pipe is being closed
	at java.base/java.io.FileInputStream.readBytes(Native Method)
	at java.base/java.io.FileInputStream.read(FileInputStream.java:287)
	at java.base/java.io.BufferedInputStream.fill(BufferedInputStream.java:291)
	at java.base/java.io.BufferedInputStream.implRead(BufferedInputStream.java:325)
	at java.base/java.io.BufferedInputStream.read(BufferedInputStream.java:312)
	at org.jline.Test1.testBreaks(Test1.java:16)
	at java.base/java.lang.reflect.Method.invoke(Method.java:580)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1597)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1597)

The code I use to create my terminal:

TerminalBuilder.builder().dumb(true).build(); // throws exception on next read, either from System.in or LineReaderBuilder...
TerminalBuilder.builder().dumb(true).exec(false).build(); // works

My primitive suggestion is to modify the ProcessBuilder not to use inheritIO, like the example below, which works.
Now I assume that my environment is somehow causing this issue, with my PATH being kinda messy and everything working on my laptop. That is also why it is kind of hard to reproduce. However, I also believe jline3 should not be affected by such things and continue to function.

To otherwise mitigate this problem as a jline3 user, the easiest option I found is to set exec(false) for the TerminalBuilder.
To be precise: even if the final created terminal is NOT exec, it still breaks, because of the check always being executed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant