You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@mina.apache.org by "beijishiqidu (via GitHub)" <gi...@apache.org> on 2023/05/19 10:12:16 UTC

[GitHub] [mina-sshd] beijishiqidu commented on issue #371: The timeout interval from the client SftpClient cannot be configured on the current server.

beijishiqidu commented on issue #371:
URL: https://github.com/apache/mina-sshd/issues/371#issuecomment-1554346083

   @tomaswolf 
   
   Hello, friend.
   
   I wrote all kinds of test cases, Here's just one example
   
   ```java
   private static SftpClient sftpClient;
   
       private static SftpFileSystem sftpFileSystem;
   
       public static void main(String[] args) throws Exception {
   
           Runnable runnable = new UploadFile();
           Thread thread1 = new Thread(runnable);
           thread1.start();
           thread1.join();
   
           Thread thread2 = new Thread(runnable);
           thread2.start();
           thread2.join();
   
           Thread thread3 = new Thread(runnable);
           thread3.start();
           thread3.join();
       }
   
       private static synchronized SftpClient getSftpClient() throws IOException {
           if (sftpClient != null) {
               return sftpClient;
           }
           sftpClient = getSftpFileSystem().getClient();
           return sftpClient;
       }
   
       private static synchronized SftpFileSystem getSftpFileSystem() throws IOException {
           if (sftpFileSystem != null) {
               return sftpFileSystem;
           }
           log.info("first init client");
           SshClient client = SshClient.setUpDefaultClient();
           client.start();
   
           ClientSession session = client.connect("admin", "127.0.0.1", 9120).verify().getSession();
           session.addPasswordIdentity("admin");
           session.auth().verify();
           session.setSessionHeartbeat(SessionHeartbeatController.HeartbeatType.IGNORE, Duration.ofMillis(5000));
           sftpFileSystem = DefaultSftpClientFactory.INSTANCE.createSftpFileSystem(session);
           return sftpFileSystem;
       }
   
       private static class UploadFile implements Runnable {
   
           @Override
           public void run() {
               for (int i = 0; i < 3; i++) {
                   try (FileInputStream in = new FileInputStream(
                       "D:\\20230113\\202301131049" + i + ".dump")) {
                       SftpPath sftpPath = getSftpFileSystem().getPath(
                           "202301131049.dump" + Thread.currentThread().getId() + i + ".tmp");
                       Files.copy(in, sftpPath);
                       getSftpClient().rename("202301131049.dump" + Thread.currentThread().getId() + i + ".tmp",
                           "202301131049.dump" + Thread.currentThread().getId() + i + ".dump");
                   } catch (Exception e) {
                       e.printStackTrace();
                   }
               }
           }
       }
   ```
   As in the example above, I just want to use the same SftpClient object in different threads.  
   
   However, I observe the server through jstack. Each time a thread is started, the server generates a thread of the SftpSubsystem object and is in the waiting state. But, in fact, my first thread's upload task is already complete.
   
   ```shell
   # first time:
   $ jstack.exe -l 56192 |grep sshd-Sftp
   "sshd-SftpSubsystem-40668-thread-1" #41 daemon prio=5 os_prio=0 tid=0x00000000290e0000 nid=0xc67c runnable [0x0000000000b8e000]
   
   
   # second time:
   $ jstack.exe -l 56192 |grep sshd-Sftp
   "sshd-SftpSubsystem-60480-thread-1" #42 daemon prio=5 os_prio=0 tid=0x00000000290e1800 nid=0x94c4 waiting on condition [0x000000002be5f000]
   "sshd-SftpSubsystem-40668-thread-1" #41 daemon prio=5 os_prio=0 tid=0x00000000290e0000 nid=0xc67c waiting on condition [0x0000000000b8f000]
   
   #third time:
   
   $ jstack.exe -l 56192 |grep sshd-Sftp
   "sshd-SftpSubsystem-57236-thread-1" #43 daemon prio=5 os_prio=0 tid=0x00000000290e4000 nid=0xa48c waiting on condition [0x000000002bf5f000]
   "sshd-SftpSubsystem-60480-thread-1" #42 daemon prio=5 os_prio=0 tid=0x00000000290e1800 nid=0x94c4 waiting on condition [0x000000002be5f000]
   "sshd-SftpSubsystem-40668-thread-1" #41 daemon prio=5 os_prio=0 tid=0x00000000290e0000 nid=0xc67c waiting on condition [0x0000000000b8f000]
   ```
   
   and the detail jstack of thread sshd-SftpSubsystem-57236-thread-1 like this:
   ```java
   "sshd-SftpSubsystem-57236-thread-1" #31 daemon prio=5 os_prio=0 tid=0x000000002a046000 nid=0xe130 waiting on condition [0x000000000096f000]
      java.lang.Thread.State: WAITING (parking)
           at sun.misc.Unsafe.park(Native Method)
           - parking to wait for  <0x00000005c2b66680> (a java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject)
           at java.util.concurrent.locks.LockSupport.park(LockSupport.java:175)
           at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2045)
           at java.util.concurrent.LinkedBlockingQueue.take(LinkedBlockingQueue.java:442)
           at org.apache.sshd.sftp.server.SftpSubsystem.run(SftpSubsystem.java:297)
           at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
           at java.util.concurrent.FutureTask.run$$$capture(FutureTask.java:266)
           at java.util.concurrent.FutureTask.run(FutureTask.java)
           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
           at java.lang.Thread.run(Thread.java:748)
   
      Locked ownable synchronizers:
           - <0x00000005c2b66898> (a java.util.concurrent.ThreadPoolExecutor$Worker)
   ```
   
   I tried to look at the source code for this SftpSubsystem, and I found that it kept fetching values from the blocking queue.
   
   ```java
   try {
               ChannelSession channel = getServerChannelSession();
               LocalWindow localWindow = channel.getLocalWindow();
               while (true) {
                   Buffer buffer = requests.take();
                   if (buffer == CLOSE) {
                       break;
                   }
                   buffersCount++;
                   process(buffer);
                   localWindow.check();
               }
           } catch (Throwable t) {
   ```
   
   So, I don't know how to close these objects, or if there's a timeout configuration that allows the object to be destroyed.
   
   


-- 
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-unsubscribe@mina.apache.org

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


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