Invoking new SSHClient() never finishes
- Dominant language
- Java
- Stars
- 2.7k
- Forks
- 620
- Avg merge
- 3d 23h
- Merged PRs (30d)
- 11
Description
(note: I found this issue while trying to circumvent issue #612 )
I've been using the library for quite some time (version 0.27.0) for opening connections to network devices and executing commands on them. I recently encountered a problem creating new instances of SSHClient():
If I only create a single client, I encounter different problems with the channels opened by sshClient. (Will be opening a separate issue shortly), so I tried opening many ssh clients to check if that issue persists.
Surprisingly, I found out many clients never finished the invocation of their own constructor.
Minimal reproducible environment:
```
Ubuntu 16.04.5 LTS (GNU/Linux 4.4.0-131-generic x86_64)
JDK 11
```
Source code:
```
for(int i = 0; i<=100; i++) {
AtomicInteger counter = new AtomicInteger(i);
threadingManager.submit(() -> { // submits the lambda to a central thread pool for concurrent execution
try {
logger.fatal("Before creating ssh client #"+counter.get());
final SSHClient sshClient = new SSHClient();
logger.fatal("After creating ssh client #"+counter.get());
} catch (Exception e) {
e.printStackTrace();
}
});
}
```
Output:

After double checking, I found out that:
1) running the code above sequentially works using the code below, but is extremely slow (each new client takes longer than the previous one)
```
for(int i = 0; i<=100; i++) {
try {
logger.fatal("Before creating ssh client #"+i);
final SSHClient sshClient = new SSHClient();
logger.fatal("After creating ssh client #"+i);
} catch (Exception e) {
e.printStackTrace();
}
}
```
2) running the original example with the "synchronized" keyword using the code below has the same results as the sequential example (which is quite logical, since it implies only one thread can create a new SSHClient at a time)
for(int i = 0; i<=100; i++) {
AtomicInteger counter = new AtomicInteger(i);
threadingManager.submit(() -> {
try {
logger.fatal("Before creating ssh client #"+counter.get());
synchronized (this) { //this is a singleton
final SSHClient sshClient = new SSHClient();
}
logger.fatal("After creating ssh client #"+counter.get());
} catch (Exception e) {
e.printStackTrace();
}
});
}
3) After investigating the source code, I found the problematic part was in the BouncyCastleRandom constructor, line 21:
....= (new SecureRandom()).generateSeed(8);
Checking across the web, there were multiple issues regarding the implementation used by Java in their source code (notabely [here](https://stackoverflow.com/questions/58991966/what-java-security-egd-option-is-for) and [here](https://stackoverflow.com/questions/58853372/what-exactly-does-djava-security-egd-file-dev-urandom-do-when-containerizi)).
Thanks for your help on this matter
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.