JDK-8346805 : JLine update to System.console interferes with existing Java SignalHandler
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.io
  • Priority: P4
  • Status: Resolved
  • Resolution: Delivered
  • Submitted: 2024-12-24
  • Updated: 2025-04-21
  • Resolved: 2025-04-02
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
JDK 25
25Resolved
Related Reports
Relates :  
Relates :  
Relates :  
Description
Handling a signal using `jdk.unsupported/share/classes/sun/misc/SignalHandler.java` is failing since `22+b08`.

Looks like it was the change:
8308591: JLine as the default Console provider

JLine uses Signal.
Running with -Djdk.console=java.base does restore the old working signal behaviour.

### Reproduction

```
$ cat Jdk8346805_SignalHandlerJLineTest.java
import sun.misc.Signal;
public final class Jdk8346805_SignalHandlerJLineTest {
    public static void main(String[] args) throws java.io.IOException {
        Signal.handle(new Signal("INT"), signal -> System.out.format("[%s]", signal));
        while (true) { if ("x".equals(System.console().readLine())) { break; } }
    }
}

$ ~/oracle/jdk-22.0.2/bin/java Jdk8346805_SignalHandlerJLineTest.java
asd
foo
ff
[PRESSING CTRL+C AT THIS POINT]
Exception in thread "main" jdk.internal.org.jline.reader.UserInterruptException
	at jdk.internal.le/jdk.internal.org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:717)
	at jdk.internal.le/jdk.internal.org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:468)
	at jdk.internal.le/jdk.internal.org.jline.JdkConsoleProviderImpl$JdkConsoleImpl.readLine(JdkConsoleProviderImpl.java:98)
	at jdk.internal.le/jdk.internal.org.jline.JdkConsoleProviderImpl$JdkConsoleImpl.readLine(JdkConsoleProviderImpl.java:106)
	at java.base/java.io.ProxyingConsole.readLine(ProxyingConsole.java:122)
	at Jdk8346805_SignalHandlerJLineTest.main(Jdk8346805_SignalHandlerJLineTest.java:5)

$ ~/oracle/jdk-22.0.2/bin/java -Djdk.console=java.base Jdk8346805_SignalHandlerJLineTest.java
asd
foo
^C[SIGINT]

^C[SIGINT]

x
```

A command-line app that reads the terminal is likely to have found System.console() useful, and is also likely to be the kind of app that found this way of installing a SignalHandler to protect itself from accidental control-C killing the app.

Comments
Delivered with the fix to JDK-8351435
02-04-2025

Assigning this to Jan for further investigation in JLine
02-01-2025

Possibly related to JDK-8332921, as its root cause is JLine signal handling interfering with Hotspot signal handling. See [~jlahoda].
26-12-2024

At the point where `UserInterruptException` is thrown, stack trace of the discarded `InterruptedException` is as follows: ``` Caused by: java.io.InterruptedIOException at jdk.internal.le/jdk.internal.org.jline.terminal.impl.AbstractPty.checkInterrupted(AbstractPty.java:89) at jdk.internal.le/jdk.internal.org.jline.terminal.impl.AbstractPty$PtyInputStream.read(AbstractPty.java:131) at jdk.internal.le/jdk.internal.org.jline.utils.NonBlockingInputStream.read(NonBlockingInputStream.java:62) at jdk.internal.le/jdk.internal.org.jline.utils.NonBlocking$NonBlockingInputStreamReader.read(NonBlocking.java:157) at jdk.internal.le/jdk.internal.org.jline.utils.NonBlockingReader.read(NonBlockingReader.java:56) at jdk.internal.le/jdk.internal.org.jline.keymap.BindingReader.readCharacter(BindingReader.java:159) ... 15 more ```
24-12-2024

Apologies - the console.readLine() call is required, e.g. import sun.misc.Signal; import sun.misc.SignalHandler; import java.io.*; public final class SignalTest { public static void main(String[] args) throws IOException { System.out.println("Configuring `INT` signal handler..."); SignalHandler handler = signal -> System.out.format("[%s]", signal); Signal.handle(new Signal("INT"), handler); Console con = System.console(); System.out.println("Try `CTRL-C`... (Type `x` to quit)"); while (true) { if ("x".equals(con.readLine())) { break; } } } }
24-12-2024