Skip to content

Commit 6bcd715

Browse files
committed
GH-721: Create session timeout thread on demand
Only schedule the SessionTimeoutListener when the first session is created. Cancel it when there are no more sessions. Re-schedule it when there are sessions again. So the session timeout listener is running periodically only when there are sessions. This prevents the up-front creation of these timer threads when an SftpFileSystemProvider is instantiated.
1 parent 5a9194b commit 6bcd715

1 file changed

Lines changed: 35 additions & 7 deletions

File tree

sshd-core/src/main/java/org/apache/sshd/common/helpers/AbstractFactoryManager.java

Lines changed: 35 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@
5555
import org.apache.sshd.common.random.Random;
5656
import org.apache.sshd.common.session.ConnectionService;
5757
import org.apache.sshd.common.session.ReservedSessionMessagesHandler;
58+
import org.apache.sshd.common.session.Session;
5859
import org.apache.sshd.common.session.SessionDisconnectHandler;
5960
import org.apache.sshd.common.session.SessionListener;
6061
import org.apache.sshd.common.session.UnknownChannelReferenceHandler;
@@ -472,31 +473,58 @@ public void removePortForwardingEventListener(PortForwardingEventListener listen
472473
}
473474

474475
protected void setupSessionTimeout(AbstractSessionFactory<?, ?> sessionFactory) {
475-
// set up the the session timeout listener and schedule it
476476
sessionTimeoutListener = createSessionTimeoutListener();
477477
addSessionListener(sessionTimeoutListener);
478-
479-
timeoutListenerFuture = getScheduledExecutorService()
480-
.scheduleAtFixedRate(sessionTimeoutListener, 1, 1, TimeUnit.SECONDS);
481478
}
482479

483480
protected void removeSessionTimeout(AbstractSessionFactory<?, ?> sessionFactory) {
484481
stopSessionTimeoutListener(sessionFactory);
485482
}
486483

487484
protected SessionTimeoutListener createSessionTimeoutListener() {
488-
return new SessionTimeoutListener();
485+
return new SessionTimeoutListener() {
486+
487+
@Override
488+
public void sessionCreated(Session session) {
489+
synchronized (this) {
490+
super.sessionCreated(session);
491+
if (!sessions.isEmpty()) {
492+
ensureTimeoutScheduled();
493+
}
494+
}
495+
}
496+
497+
@Override
498+
public void sessionClosed(Session s) {
499+
synchronized (this) {
500+
super.sessionClosed(s);
501+
if (sessions.isEmpty()) {
502+
cancelSessionTimeout();
503+
}
504+
}
505+
}
506+
};
489507
}
490508

491-
protected void stopSessionTimeoutListener(AbstractSessionFactory<?, ?> sessionFactory) {
492-
// cancel the timeout monitoring task
509+
private void ensureTimeoutScheduled() {
510+
if (timeoutListenerFuture == null) {
511+
timeoutListenerFuture = getScheduledExecutorService().scheduleAtFixedRate(sessionTimeoutListener, 1, 1,
512+
TimeUnit.SECONDS);
513+
}
514+
}
515+
516+
private void cancelSessionTimeout() {
493517
if (timeoutListenerFuture != null) {
494518
try {
495519
timeoutListenerFuture.cancel(true);
496520
} finally {
497521
timeoutListenerFuture = null;
498522
}
499523
}
524+
}
525+
526+
protected void stopSessionTimeoutListener(AbstractSessionFactory<?, ?> sessionFactory) {
527+
cancelSessionTimeout();
500528

501529
// remove the sessionTimeoutListener completely; should the SSH server/client be restarted, a new one
502530
// will be created.

0 commit comments

Comments
 (0)