jline / jline3

JLine is a Java library for handling console input.
Other
1.46k stars 214 forks source link

CTRL-C EXITS APPLICATION EVEN WHEN HANDLED #938

Open philiprichens opened 7 months ago

philiprichens commented 7 months ago

I have attached a short test program which shows the issue with CTRL-C handling in 3.25.0. The program has a handler for Terminal.Signal.INT and it also catches UserInterruptException.

In 3.21, when I press CTRL-C, either the handler is invoked or the UserInterruptException is caught and I can process the CTRL-C and continue with the read loop.

In 3.25.0 (on Windows at least), the exception is thrown and at the same time the application is exited. This makes the application unusable.

As well as the test program I've attached screen shots showing the behaviour in both 3.21.0 and 3.25.0.

Screenshot-3 21 Screenshot-3 25

package testctlc;

import java.io.IOException;
import org.jline.reader.EndOfFileException;
import org.jline.reader.LineReader;
import org.jline.reader.LineReaderBuilder;
import org.jline.reader.UserInterruptException;
import org.jline.terminal.Terminal;
import org.jline.terminal.TerminalBuilder;
import org.jline.utils.Log;

public class TestCtlC {

    public static void main(String[] args) throws IOException {
        TestCtlC tester = new TestCtlC();
        tester.processInput();
    }

    private final Terminal terminal;
    private final LineReader reader;
    private boolean interrupted = false;

    public TestCtlC() throws IOException {
        terminal = TerminalBuilder.builder().build();
        Log.info(terminal.getClass().getSimpleName());
        terminal.handle(Terminal.Signal.INT, signal -> {
            interrupted = true;
            Log.info("interrupt");
        });
        reader = LineReaderBuilder.builder()
                .terminal(terminal)
                .build();
    }

    public void processInput() {
        while (true) {
            try {
                interrupted = false;
                String line = reader.readLine("TESTCTLC> ");
                if (line.equalsIgnoreCase("QUIT")) {
                    System.exit(0);
                } else if (line.equalsIgnoreCase("SLEEP")) {
                    for (int c = 0; !interrupted && c < 1000; c++) {
                        Thread.sleep(10);
                    }
                }
            } catch (UserInterruptException | EndOfFileException | InterruptedException ex) {
                Log.error(ex.getClass().getSimpleName());
            }
        }
    }
}
gnodet commented 7 months ago

Could you try with 3.25.1 ? I've fixed a bunch of bugs in there.

philiprichens commented 7 months ago

I'm afraid it is still showing up when I run with 3.25.1.

gnodet commented 6 months ago

Looks duplicated by #940

VerKWer commented 6 months ago

Seems maybe Windows specific? I can't reproduce this on a Linux box with the provided test program (both on 3.25.0 and 3.25.1).

philiprichens commented 6 months ago

Yes, I agree, it is Windows specific.

gnodet commented 6 months ago

@philiprichens reproducer seems to work for me:

image

Not sure how to address the issue. One possibility if you have a bit of time would be to performa a git-bisect on jline between 3.21.0 and 3.25.0 and pinpoint the exact problem.

Could this also be related to the JDK used ? I was using OpenJDK 21.0.2 in the above test.

gnodet commented 5 months ago

I tried again, but I cannot reproduce it on windows 11 + cmd console.

jvalkeal commented 4 months ago

I also played with this when I was poking other windows related issues. I was on jdk17 so while possible probably not jdk related thing. Almost feels like windows terminal related issue which also feels weird as it doesn't update that often via official channel.

It'd be nice to see this sample in a repo to actually run same code.