Skip to content

Commit

Permalink
JENKINS-71798: TimeoutService threads are left after closing connecti…
Browse files Browse the repository at this point in the history
…on (#155)

* JENKINS-71798: TimeoutService threads are left after closing connection

* Update src/com/trilead/ssh2/util/TimeoutService.java

Co-authored-by: Ivan Fernandez Calvo <[email protected]>

* Update TimeoutService.java

---------

Co-authored-by: Ivan Fernandez Calvo <[email protected]>
  • Loading branch information
mpet and kuisathaverat authored Sep 5, 2023
1 parent 252c3c4 commit a969bd3
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 15 deletions.
7 changes: 4 additions & 3 deletions src/com/trilead/ssh2/Connection.java
Original file line number Diff line number Diff line change
Expand Up @@ -665,7 +665,8 @@ final class TimeoutState
if (kexTimeout < 0)
throw new IllegalArgumentException("kexTimeout must be non-negative!");

final TimeoutState state = new TimeoutState();
final TimeoutState state = new TimeoutState();
final TimeoutService timeoutService = new TimeoutService(hostname);

tm = new TransportManager(hostname, port, sourceAddress);

Expand Down Expand Up @@ -713,7 +714,7 @@ public void run()

long timeoutHorizont = System.currentTimeMillis() + kexTimeout;

token = TimeoutService.addTimeoutHandler(timeoutHorizont, timeoutHandler);
token = timeoutService.addTimeoutHandler(timeoutHorizont, timeoutHandler);
}

try
Expand All @@ -737,7 +738,7 @@ public void run()

if (token != null)
{
TimeoutService.cancelTimeoutHandler(token);
timeoutService.cancelTimeoutHandler(token);

/* Were we too late? */

Expand Down
35 changes: 23 additions & 12 deletions src/com/trilead/ssh2/util/TimeoutService.java
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
Expand All @@ -20,25 +21,33 @@
* @version $Id: TimeoutService.java,v 1.1 2007/10/15 12:49:57 cplattne Exp $
*/
public class TimeoutService {

private final static ThreadFactory threadFactory = new ThreadFactory() {

private AtomicInteger count = new AtomicInteger();



private ScheduledFuture<?> scheduledFuture;
private final String hostname;
private final ThreadFactory threadFactory = new ThreadFactory() {
private AtomicInteger count = new AtomicInteger();
@Override
public Thread newThread(Runnable r) {
int threadNumber = count.incrementAndGet();
String threadName = "TimeoutService-" + threadNumber;
String threadName = "Trilead_TimeoutService_" + hostname + "-" + threadNumber;
Thread thread = new Thread(r, threadName);
thread.setDaemon(true);
return thread;
}
};
private final ScheduledExecutorService scheduler = Executors.newSingleThreadScheduledExecutor(threadFactory);

public TimeoutService(String hostname){
this.hostname = hostname;
}



private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(20, threadFactory);

public static class TimeoutToken implements Runnable {
public class TimeoutToken implements Runnable {
private Runnable handler;
private boolean cancelled = false;
private volatile boolean cancelled = false;

public void run() {
if (!cancelled) {
Expand All @@ -54,14 +63,14 @@ public void run() {
* @param handler handler
* @return a TimeoutToken that can be used to cancel the timeout.
*/
public static final TimeoutToken addTimeoutHandler(long runTime, Runnable handler) {
public TimeoutToken addTimeoutHandler(long runTime, Runnable handler) {
TimeoutToken token = new TimeoutToken();
token.handler = handler;
long delay = runTime - System.currentTimeMillis();
if (delay < 0) {
delay = 0;
}
scheduler.schedule(token, delay, TimeUnit.MILLISECONDS);
scheduledFuture = scheduler.schedule(token, delay, TimeUnit.MILLISECONDS);
return token;
}

Expand All @@ -70,7 +79,9 @@ public static final TimeoutToken addTimeoutHandler(long runTime, Runnable handle
*
* @param token token to be canceled.
*/
public static final void cancelTimeoutHandler(TimeoutToken token) {
public void cancelTimeoutHandler(TimeoutToken token) {
token.cancelled = true;
scheduledFuture.cancel(true);
scheduler.shutdownNow();
}
}

0 comments on commit a969bd3

Please sign in to comment.