jline / jline3

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

Less and Apache MINA SSHD: Infinite Loop when forcibly terminating a SSH session. #356

Open markusju opened 5 years ago

markusju commented 5 years ago

Description

We have noticed an issue with jline3's "Less" implementation in combination with Apache MINA SSHD resulting in an infinite loop, when forcibly terminating a SSH session (i.e. closing the terminal window) while Less is running.

Reproducing the Issue

The following snippet allows to reproduce the issue. Once the SSH sessions is established and you are seeing the Less screen, forcibly terminate the session by closing the terminal window. The thread handling the ssh connection will then begin to burn CPU cycles entering an infinite loop.

Versions: jLine3 3.10.0 Apache SSHD 2.0.0

        SshServer sshServer = SshServer.setUpDefaultServer();
        sshServer.setKeyPairProvider(new SimpleGeneratorHostKeyProvider());
        sshServer.setPasswordAuthenticator((username, password, session) -> true);
        sshServer.setShellFactory(new ShellFactoryImpl((x)-> {
            Less less = new Less(x.getTerminal());
            try {
                less.run(new Source() {
                    @Override
                    public String getName() {
                        return "Test File";
                    }

                    @Override
                    public InputStream read() throws IOException {
                        return new ByteArrayInputStream("Oh my god, Becky. \n\n Look at that InputStream.".getBytes());
                    }
                });
            } catch (IOException | InterruptedException e) {
                e.printStackTrace();
            }
        }));
        sshServer.setHost("127.0.0.1");
        sshServer.setPort(2223);

        sshServer.start();

        Thread.sleep(60*1000);

We have extracted the following stack trace of the thread burning the cycles.

"Thread-2@2917" daemon prio=5 tid=0x16 nid=NA runnable
  java.lang.Thread.State: RUNNABLE
      at org.apache.sshd.common.channel.ChannelOutputStream.flush(ChannelOutputStream.java:174)
      - locked <0xbf4> (a org.apache.sshd.common.channel.ChannelOutputStream)
      at org.jline.terminal.impl.LineDisciplineTerminal$FilteringOutputStream.flush(LineDisciplineTerminal.java:301)
      at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:318)
      at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:153)
      - locked <0xbf7> (a java.io.OutputStreamWriter)
      at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:254)
      at java.io.PrintWriter.flush(PrintWriter.java:396)
      at org.jline.terminal.impl.AbstractTerminal.flush(AbstractTerminal.java:159)
      at org.jline.utils.Display.update(Display.java:331)
      at org.jline.utils.Display.update(Display.java:99)
      at org.jline.builtins.Less.display(Less.java:634)
      - locked <0xbfc> (a org.jline.builtins.Less)
      at org.jline.builtins.Less.run(Less.java:384)
      at org.jline.builtins.Less.run(Less.java:109)
      at a.b.c.JlineIssue.lambda$main$1(JlineIssue.java:32)
      at a.b.c.JlineIssue$$Lambda$79.116734858.accept(Unknown Source:-1)
      at org.jline.builtins.ssh.ShellFactoryImpl$ShellImpl.run(ShellFactoryImpl.java:225)
      at org.jline.builtins.ssh.ShellFactoryImpl$ShellImpl.lambda$start$0(ShellFactoryImpl.java:107)
      at org.jline.builtins.ssh.ShellFactoryImpl$ShellImpl$$Lambda$124.2010899121.run(Unknown Source:-1)
      at java.lang.Thread.run(Thread.java:834)
gnodet commented 5 years ago

I've tried running the demo with ssh, setting up the server, connecting with a native ssh client, running less, killing -9 the client. This does not seem to lead to the problem you describe.