FerrariCalifornia commented on issue #414:
URL: https://github.com/apache/mina-sshd/issues/414#issuecomment-1709350807

   we did not try 2.10.0
   
   Here is the code I suspect is causing the problem
   
sshd-core/src/main/java/org/apache/sshd/common/session/helpers/KeyExchangeMessageHandler.java
   
   as we can see ,  KexState state = session.kexState.get();   when the session 
is already close,but key exchage not completed
   the code may hava an infinite loop 
   
   
   
   when the debug log print 
   
   `2023-09-06 16:19:59.524 [transferEpQueryReq-thread-8] DEBUG 
org.apache.sshd.server.session.ServerSessionImpl   282  [] 
writeOrEnqueue(ServerSessionImpl[itran@/200.200.60.22:47442])[SSH_MSG_CHANNEL_DATA]:
 Blocking thread Thread[transferEpQueryReq-thread-8,5,main] until KEX is over 
or timeout 10000 MILLISECONDS`
   
   i have chacked the session 200.200.60.22:47442 its already closed
   
   
   
sshd-core/src/main/java/org/apache/sshd/common/session/helpers/KeyExchangeMessageHandler.java
   ```
   /**
        * Writes an SSH packet. If no KEX is ongoing and there are no pending 
packets queued to be written after KEX, the
        * buffer is written directly. Otherwise, the write is enqueued or the 
calling thread is blocked until all pending
        * packets have been written, depending on the result of {@link 
#isBlockAllowed(int)}. If the calling thread holds
        * the monitor of the session's {@link AbstractSession#getFutureLock()}, 
it is never blocked and the write is
        * queued.
        * <p>
        * If {@code timeout <= 0} or {@code unit == null}, a time-out of 
"forever" is assumed. Note that a timeout applies
        * only if the calling thread is blocked.
        * </p>
        *
        * @param  cmd         SSH command from the buffer
        * @param  buffer      {@link Buffer} containing the packet to write
        * @param  timeout     number of {@link TimeUnit}s to wait at most if 
the calling thread is blocked
        * @param  unit        {@link TimeUnit} of {@code timeout}
        * @return             an {@link IoWriteFuture} that will be fulfilled 
once the packet has indeed been written.
        * @throws IOException if an error occurs
        */
       protected IoWriteFuture writeOrEnqueue(int cmd, Buffer buffer, long 
timeout, TimeUnit unit) throws IOException {
           boolean holdsFutureLock = Thread.holdsLock(session.getFutureLock());
           for (;;) {
               DefaultKeyExchangeFuture block = null;
               // We must decide _and_ write the packet while holding the lock. 
If we'd write the packet outside this
               // lock, there is no guarantee that a concurrently running 
KEX_INIT received from the peer doesn't change
               // the state to RUN and grabs the encodeLock before the thread 
executing this write operation. If this
               // happened, we might send a high-level messages after our 
KEX_INIT, which is not allowed by RFC 4253.
               //
               // Use the readLock here to give KEX state updates and the 
flushing thread priority.
               lock.readLock().lock();
               try {
                   if (shutDown) {
                       throw new SshException("Write attempt on closing 
session: " + SshConstants.getCommandMessageName(cmd));
                   }
                   KexState state = session.kexState.get();
                   boolean kexDone = KexState.DONE.equals(state) || 
KexState.KEYS.equals(state);
                   if (kexDone && kexFlushed) {
                       // Not in KEX, no pending packets: out it goes.
                       return session.doWritePacket(buffer);
                   } else if (!holdsFutureLock && isBlockAllowed(cmd)) {
                       // KEX done, but still flushing: block until flushing is 
done, if we may block.
                       //
                       // The future lock is a _very_ global lock used for 
synchronization in many futures, and in
                       // particular in the key exchange related futures; and 
it is accessible by client code. If we
                       // block a thread holding that monitor, none of the 
futures that use that lock can ever be
                       // fulfilled, including the future this thread would 
wait upon.
                       //
                       // It would seem that calling writePacket() while 
holding *any* (session global) Apache MINA
                       // sshd lock in client code would be extremely bad 
practice. But note that the deprecated
                       // ClientUserAuthServiceOld does exactly that. While 
that deprecated service doesn't send
                       // channel data, there might be client code that does 
similar things. But this is also the
                       // reason why we must be careful to never synchronize on 
the futureLock while holding the
                       // kexLock: if that happened while code concurrently 
running called writePacket() while holding
                       // the futureLock, we might get a deadlock due to lock 
inversion.
                       //
                       // Blocking here will prevent data-pumping application 
threads from overrunning the flushing
                       // thread and ensures that the flushing thread does 
indeed terminate.
                       //
                       // Note that we block only for channel data.
                       block = kexFlushedFuture;
                   } else {
                       // Still in KEX or still flushing and we cannot block 
the thread. Enqueue the packet; it will
                       // get written by the flushing thread at the end of KEX. 
Note that theoretically threads may
                       // queue arbitrarily many packets during KEX. However, 
such a scenario is mostly limited to
                       // "data pumping" threads that typically will block 
during KEX waiting until window space is
                       // available on the channel again, which can happen only 
at the end of KEX.
                       // (SSH_CHANNEL_WINDOW_ADJUST is not a low-level message 
and will not be sent during KEX.)
                       //
                       // If so many packets are queued that flushing them 
triggers another KEX flushing stops
                       // and will be resumed at the end of the new KEX.
                       if (kexDone && log.isDebugEnabled()) {
                           log.debug("writeOrEnqueue({})[{}]: Queuing packet 
while flushing", session,
                                   SshConstants.getCommandMessageName(cmd));
                       }
                       return enqueuePendingPacket(cmd, buffer);
                   }
               } finally {
                   lock.readLock().unlock();
               }
               if (block != null) {
                   if (timeout <= 0 || unit == null) {
                       if (log.isDebugEnabled()) {
                           log.debug("writeOrEnqueue({})[{}]: Blocking thread 
{} until KEX is over", session,
                                   SshConstants.getCommandMessageName(cmd), 
Thread.currentThread());
                       }
                       block.await();
                   } else {
                       if (log.isDebugEnabled()) {
                           log.debug("writeOrEnqueue({})[{}]: Blocking thread 
{} until KEX is over or timeout {} {}", session,
                                   SshConstants.getCommandMessageName(cmd), 
Thread.currentThread(), timeout, unit);
                       }
                       block.await(timeout, unit);
                   }
                   if (log.isDebugEnabled()) {
                       log.debug("writeOrEnqueue({})[{}]: Thread {} awakens 
after KEX done", session,
                               SshConstants.getCommandMessageName(cmd), 
Thread.currentThread());
                   }
               }
           }
       }
   ```


-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: dev-unsubscr...@mina.apache.org

For queries about this service, please contact Infrastructure at:
us...@infra.apache.org


---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscr...@mina.apache.org
For additional commands, e-mail: dev-h...@mina.apache.org

Reply via email to