title: Jsch - Opening multiple channels in a single session to SLES15 server is failing
body: <p>When executing commands by opening multiple channels in a single session to a SLES server is failing. This same code is working with all versions of SLES12, Centos7 and Centos8.</p>
  <p><strong>JSCH version:</strong> 0.1.55</p>
  <p><strong>SSH Server Machine Details</strong><br />
  OS: SUSE Linux Enterprise Server 15 SP2<br />
  SSHD: OpenSSH_8.1p1, OpenSSL 1.1.1d</p>
  <p><strong>These are the errors in /var/log/messages:</strong><br />
  fatal: mm_answer_audit_server_key_free: buffer error: incomplete message<br />
  fatal: mm_request_receive: read: Connection reset by peer<br />
  fatal: mm_request_send: write: Broken pipe</p>
  <p><strong>This is the error in JSCH log:</strong><br />
  INFO:    Connecting to 10.75.32.47 port 22<br />
  INFO:    Connection established<br />
  INFO:    Remote version string: SSH-2.0-OpenSSH_8.1<br />
  INFO:    Local version string: SSH-2.0-JSCH-0.1.54<br />
  INFO:    CheckCiphers: aes256-ctr,aes192-ctr,aes128-ctr,aes256-cbc,aes192-cbc,aes128-cbc,3des-ctr,arcfour,arcfour128,arcfour256<br />
  INFO:    CheckKexes: diffie-hellman-group14-sha1,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521<br />
  INFO:    CheckSignatures: ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521<br />
  INFO:    SSH_MSG_KEXINIT sent<br />
  INFO:    SSH_MSG_KEXINIT received<br />
  INFO:    kex: server: curve25519-sha256,curve25519-sha256@libssh.org,ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group-exchange-sha256,diffie-hellman-group16-sha512,diffie-hellman-group18-sha512,diffie-hellman-group14-sha256,diffie-hellman-group14-sha1<br />
  INFO:    kex: server: rsa-sha2-512,rsa-sha2-256,ssh-rsa,ecdsa-sha2-nistp256,ssh-ed25519<br />
  INFO:    kex: server: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com<br />
  INFO:    kex: server: chacha20-poly1305@openssh.com,aes128-ctr,aes192-ctr,aes256-ctr,aes128-gcm@openssh.com,aes256-gcm@openssh.com<br />
  INFO:    kex: server: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1<br />
  INFO:    kex: server: umac-64-etm@openssh.com,umac-128-etm@openssh.com,hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,hmac-sha1-etm@openssh.com,umac-64@openssh.com,umac-128@openssh.com,hmac-sha2-256,hmac-sha2-512,hmac-sha1<br />
  INFO:    kex: server: none,zlib@openssh.com<br />
  INFO:    kex: server: none,zlib@openssh.com<br />
  INFO:    kex: server:<br />
  INFO:    kex: server:<br />
  INFO:    kex: client: ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,diffie-hellman-group14-sha1,diffie-hellman-group-exchange-sha256,diffie-hellman-group-exchange-sha1,diffie-hellman-group1-sha1<br />
  INFO:    kex: client: ssh-rsa,ssh-dss,ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521<br />
  INFO:    kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc<br />
  INFO:    kex: client: aes128-ctr,aes128-cbc,3des-ctr,3des-cbc,blowfish-cbc,aes192-ctr,aes192-cbc,aes256-ctr,aes256-cbc<br />
  INFO:    kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96<br />
  INFO:    kex: client: hmac-md5,hmac-sha1,hmac-sha2-256,hmac-sha1-96,hmac-md5-96<br />
  INFO:    kex: client: none<br />
  INFO:    kex: client: none<br />
  INFO:    kex: client:<br />
  INFO:    kex: client:<br />
  INFO:    kex: server-&gt;client aes128-ctr hmac-sha1 none<br />
  INFO:    kex: client-&gt;server aes128-ctr hmac-sha1 none<br />
  INFO:    SSH_MSG_KEX_ECDH_INIT sent<br />
  INFO:    expecting SSH_MSG_KEX_ECDH_REPLY<br />
  INFO:    ssh_rsa_verify: signature true<br />
  WARN:    Permanently added '10.75.32.47' (RSA) to the list of known hosts.<br />
  INFO:    SSH_MSG_NEWKEYS sent<br />
  INFO:    SSH_MSG_NEWKEYS received<br />
  INFO:    SSH_MSG_SERVICE_REQUEST sent<br />
  INFO:    SSH_MSG_SERVICE_ACCEPT received<br />
  INFO:    Authentications that can continue: publickey,keyboard-interactive,password<br />
  INFO:    Next authentication method: publickey<br />
  INFO:    Authentications that can continue: keyboard-interactive,password<br />
  INFO:    Next authentication method: keyboard-interactive<br />
  INFO:    Authentication succeeded (keyboard-interactive).<br />
  Waiting for all tasks to finish...<br />
  INFO:    Caught an exception, leaving main loop due to Connection reset<br />
  INFO:    Disconnecting from 10.75.32.47 port 22</p>
  <pre><code>import java.util.concurrent.ExecutorService;
  import java.util.concurrent.Executors;
  import java.util.concurrent.TimeUnit;
  
  import com.jcraft.jsch.JSch;
  import com.jcraft.jsch.JSchException;
  import com.jcraft.jsch.Session;
  
  public class SSHTest {
  
      public static void main(String[] args) {
          try {
              JSch jsch = new JSch();
              Session session = jsch.getSession(&quot;userName&quot;, &quot;hostAddress&quot;, 22);
              String command = &quot;echo \&quot;Hi\&quot; &amp;&amp; sleep 1&quot;;
              java.util.Properties config = new java.util.Properties();
              config.put(&quot;StrictHostKeyChecking&quot;, &quot;no&quot;);
              config.put(&quot;PreferredAuthentications&quot;,&quot;publickey,keyboard-interactive,password&quot;);
              session.setConfig(config);
              session.setPassword(&quot;david&quot;);
              session.setTimeout(60000);
  
              session.connect();
  
              ExecutorService channelsPool = Executors.newFixedThreadPool(4);
              
              for (int i = 0; i &lt; 4; i++) {
                  channelsPool.execute(new TaskExecutor(command, session));
              }
  
              System.out.println(&quot;Waiting for all tasks to finish...&quot;);
              channelsPool.shutdown(); // Disable new tasks from being submitted
              try {
                  // Wait a while for existing tasks to terminate
                  if (!channelsPool.awaitTermination(60, TimeUnit.SECONDS)) {
                      channelsPool.shutdownNow(); // Cancel currently executing tasks
                      // Wait a while for tasks to respond to being cancelled
                      if (!channelsPool.awaitTermination(60, TimeUnit.SECONDS))
                          System.err.println(&quot;Pool did not terminate&quot;);
                  } else {
                      System.out.println(&quot;All tasks finished successfully&quot;);
                  }
              } catch (InterruptedException ie) {
                  // (Re-)Cancel if current thread also interrupted
                  channelsPool.shutdownNow();
                  // Preserve interrupt status
                  Thread.currentThread().interrupt();
              }
  
              session.disconnect();
  
              System.out.println(&quot;************************* Execution completed *************************&quot;);
          } catch (JSchException e) {
              e.printStackTrace();
          }
      }
  
  }
  </code></pre>
  <pre><code>
  import java.io.BufferedReader;
  import java.io.IOException;
  import java.io.InputStream;
  import java.io.InputStreamReader;
  import java.io.OutputStream;
  import java.util.ArrayList;
  
  import com.jcraft.jsch.ChannelExec;
  import com.jcraft.jsch.JSchException;
  import com.jcraft.jsch.Session;
  
  public class TaskExecutor implements Runnable {
  
      private String command;
      private Session session;
  
      public TaskExecutor(String command, Session session) {
          this.command = command;
          this.session = session;
      }
  
      @Override
      public void run() {
          try {
              execute();
          } catch (Exception e) {
              e.printStackTrace();
          }
      }
  
      public void execute() throws JSchException, IOException {
          ChannelExec channelExec = (ChannelExec) session.openChannel(&quot;exec&quot;);
          channelExec.setCommand(command);
          InputStream inputStream = channelExec.getInputStream();
          InputStream errorStream = channelExec.getErrStream();
          OutputStream outputStream = channelExec.getOutputStream();
          channelExec.connect();
          int exitCode = channelExec.getExitStatus();
  
          ArrayList&lt;String&gt; output = new ArrayList&lt;&gt;();
          ArrayList&lt;String&gt; error = new ArrayList&lt;&gt;();
          try (BufferedReader outputReader = new BufferedReader(new InputStreamReader(inputStream));
                  BufferedReader errorReader = new BufferedReader(new InputStreamReader(errorStream))) {
              boolean isDataLeftInStream = true;
              // Read data in output stream
              while (isDataLeftInStream) {
                  String line = outputReader.readLine();
                  if (line != null) {
                      output.add(line);
                  } else {
                      isDataLeftInStream = false;
                  }
              }
  
              // Read data in error stream
              isDataLeftInStream = true;
              while (isDataLeftInStream) {
                  String line = errorReader.readLine();
                  if (line != null) {
                      error.add(line);
                  } else {
                      isDataLeftInStream = false;
                  }
              }
          }
          
          channelExec.disconnect();
  
          System.out.println(&quot;Execution Result: \n\tExitCode=&quot; + exitCode + &quot;\n\tOutput=&quot; + String.join(&quot;\n&quot;, output)
                  + &quot;\n\tError=&quot; + String.join(&quot;\n&quot;, error));
      }
  
  }
  </code></pre>