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

SshChannelClosedException occurs when SSH client disconnects: Issue with PosixPtyTerminal and ChannelOutputStream #1060

Closed
Alexandre01Dev opened this issue Aug 18, 2024 · 3 comments
Milestone

Comments

@Alexandre01Dev
Copy link

Alexandre01Dev commented Aug 18, 2024

Hello, I am using JLINE3 with the MinaSSHD library. When creating the LineReaderImpl with the terminal generated by ShellFactoryImpl via the ShellParams consumer, and executing the readLine function, everything works fine except when the SSH client disconnects, whether the user disconnects from their terminal or is ejected by the java process, which causes an error that cannot be handled. Here it is:

org.apache.sshd.common.channel.exception.SshChannelClosedException: write(ChannelOutputStream[ChannelSession[id=0, recipient=0]-ServerSessionImpl[testuser@/217.136.124.54:8978]] SSH_MSG_CHANNEL_DATA) len=1 - channel already closed
        at org.apache.sshd.common.channel.ChannelOutputStream.write(ChannelOutputStream.java:146)
        at org.apache.sshd.common.channel.ChannelOutputStream.write(ChannelOutputStream.java:138)
        at org.jline.terminal.impl.PosixPtyTerminal.pumpOut(PosixPtyTerminal.java:227)
        at java.base/java.lang.Thread.run(Thread.java:1583)
java.io.IOError: java.io.IOException: Input/output error
        at org.jline.keymap.BindingReader.readCharacter(BindingReader.java:169)
        at org.jline.keymap.BindingReader.readBinding(BindingReader.java:109)
        at org.jline.keymap.BindingReader.readBinding(BindingReader.java:61)
        at org.jline.reader.impl.LineReaderImpl.doReadBinding(LineReaderImpl.java:974)
        at org.jline.reader.impl.LineReaderImpl.readBinding(LineReaderImpl.java:1007)
        at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:690)
        at org.jline.reader.impl.LineReaderImpl.readLine(LineReaderImpl.java:512)
        at be.alexandre01.dreamnetwork.core.console.InputThread.run(InputThread.java:40)
        at be.alexandre01.dreamnetwork.core.ssh.SSHServerCore.lambda$init$13(SSHServerCore.java:264)
        at java.base/java.lang.Thread.run(Thread.java:1583)
Caused by: java.io.IOException: Input/output error
        at java.base/java.io.FileInputStream.read0(Native Method)
        at java.base/java.io.FileInputStream.read(FileInputStream.java:231)
        at java.base/java.io.FilterInputStream.read(FilterInputStream.java:71)
        at org.jline.terminal.impl.AbstractPty$1.read(AbstractPty.java:58)
        at org.jline.terminal.impl.AbstractPty$PtyInputStream.read(AbstractPty.java:124)
        at org.jline.terminal.impl.PosixPtyTerminal$InputStreamWrapper.read(PosixPtyTerminal.java:178)
        at org.jline.utils.NonBlockingInputStream.read(NonBlockingInputStream.java:62)
        at org.jline.utils.NonBlocking$NonBlockingInputStreamReader.read(NonBlocking.java:157)
        at org.jline.utils.NonBlockingReader.read(NonBlockingReader.java:56)
        at org.jline.keymap.BindingReader.readCharacter(BindingReader.java:159)
        ... 11 more

Here are the steps to reproduce the error:

       SshServer sshd = SshServer.setUpDefaultServer();
       sshd.setPort(2222);
       sshd.setKeyPairProvider(new SimpleGeneratorHostKeyProvider(Paths.get("hostkey.ser")));
       sshd.setPasswordAuthenticator((username, password, session) -> true);
       sshd.setCipherFactories(Arrays.asList(BuiltinCiphers.aes256ctr, BuiltinCiphers.aes192ctr));
       sshd.setKeyExchangeFactories(ServerBuilder.setUpDefaultKeyExchanges(false));

       sshd.setShellFactory(new ShellFactoryImpl(shellParams -> {
           LineReader reader = LineReaderBuilder.builder()
                   .terminal(shellParams.getTerminal())
                   .build();

           try {
               String line;
               reader.printAbove("Welcome to SSH Server");
               while ((line = reader.readLine("sshTest > ")) != null) {
                   System.out.println(line);
               }
           } catch (UserInterruptException e) {
               // Ignore
           } catch (EndOfFileException e) {
               // Ignore
           }catch (Exception e){
               // ignore OTHER EXCEPTIONS
           }
       }));
       try {
           // Start the server
           sshd.start();
           System.out.println("SSH Server started on port 2222");

           // Keep the server running
           Thread.sleep(Long.MAX_VALUE);
       } catch (Exception e) {
           e.printStackTrace();
       } finally {
           try {
               sshd.stop();
           } catch (IOException e) {
               e.printStackTrace();
           }
       }
   }

Thanks for looking into this issue. If you need more details or have any suggestions, please let me know. Looking forward to your feedback

@Alexandre01Dev Alexandre01Dev changed the title PosixPtyTerminal.java closes the ChannelPipedInputStream of MINA SSHD one too many times SshChannelClosedException occurs when SSH client disconnects: Issue with PosixPtyTerminal and ChannelOutputStream Aug 18, 2024
@Alexandre01Dev Alexandre01Dev changed the title SshChannelClosedException occurs when SSH client disconnects: Issue with PosixPtyTerminal and ChannelOutputStream SshChannelClosedException occurs when SSH client disconnects: Issue with PosixPtyTerminal and ChannelOutputStream of MINA SSHD Aug 18, 2024
@Alexandre01Dev Alexandre01Dev changed the title SshChannelClosedException occurs when SSH client disconnects: Issue with PosixPtyTerminal and ChannelOutputStream of MINA SSHD SshChannelClosedException occurs when SSH client disconnects: Issue with PosixPtyTerminal and ChannelOutputStream Aug 18, 2024
@Christian-Martins
Copy link

Up !

@Alexandre01Dev
Copy link
Author

I think I found a temporary solution on Unix. In the ShellFactoryImpl class (line 204), when we force the creation of an ExternalTerminal and not a PosixPtyTerminal, the bug is gone.

gnodet added a commit to gnodet/jline3 that referenced this issue Oct 15, 2024
@gnodet gnodet added this to the 3.27.1 milestone Oct 15, 2024
@gnodet
Copy link
Member

gnodet commented Oct 15, 2024

I think this is perfectly normal for the stream to thrown an exception during the read when the stream is closed. Exceptions occurring while closing the resources can be safely ignored in this case.

@gnodet gnodet closed this as completed in 130e764 Oct 15, 2024
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

3 participants