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: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]