You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by gn...@apache.org on 2014/06/03 15:07:15 UTC

git commit: [SSHD-322] Add Closeabl#isClosed() and #isClosing()

Repository: mina-sshd
Updated Branches:
  refs/heads/master 01a515ffb -> 569fac2a3


[SSHD-322] Add Closeabl#isClosed() and #isClosing()

Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/569fac2a
Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/569fac2a
Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/569fac2a

Branch: refs/heads/master
Commit: 569fac2a3af52050b81b85f0a8860f20162324f9
Parents: 01a515f
Author: Guillaume Nodet <gn...@apache.org>
Authored: Tue Jun 3 14:51:32 2014 +0200
Committer: Guillaume Nodet <gn...@apache.org>
Committed: Tue Jun 3 14:51:32 2014 +0200

----------------------------------------------------------------------
 .../main/java/org/apache/sshd/SshServer.java    |  30 +--
 .../sshd/agent/common/AgentForwardSupport.java  |   8 +-
 .../agent/local/ChannelAgentForwarding.java     |   4 +-
 .../sshd/agent/unix/AgentForwardedChannel.java  |   4 +-
 .../sshd/agent/unix/ChannelAgentForwarding.java |   4 +-
 .../client/channel/AbstractClientChannel.java   |   8 +-
 .../sshd/client/channel/ChannelSession.java     |   4 +-
 .../client/session/ClientUserAuthService.java   |  19 +-
 .../session/ClientUserAuthServiceNew.java       |  11 +-
 .../session/ClientUserAuthServiceOld.java       |   8 +-
 .../sshd/common/AbstractFactoryManager.java     |   5 +-
 .../java/org/apache/sshd/common/Closeable.java  |  13 ++
 .../sshd/common/channel/AbstractChannel.java    |  14 +-
 .../common/forward/DefaultTcpipForwarder.java   |  47 ++---
 .../apache/sshd/common/io/mina/MinaService.java |   8 +
 .../sshd/common/io/mina/MinaServiceFactory.java |  10 +-
 .../apache/sshd/common/io/mina/MinaSession.java |   6 +
 .../sshd/common/io/nio2/Nio2Acceptor.java       |   4 +-
 .../apache/sshd/common/io/nio2/Nio2Service.java |  17 +-
 .../sshd/common/io/nio2/Nio2ServiceFactory.java |  12 +-
 .../apache/sshd/common/io/nio2/Nio2Session.java |   7 +-
 .../sshd/common/session/AbstractSession.java    |   6 +-
 .../apache/sshd/common/util/CloseableUtils.java | 186 +++++++++++++------
 .../sshd/server/channel/ChannelSession.java     |  10 +-
 .../server/session/ServerUserAuthService.java   |   8 +-
 .../sshd/server/x11/X11ForwardSupport.java      |  30 +--
 26 files changed, 290 insertions(+), 193 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/SshServer.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/SshServer.java b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
index ae39c78..7dd4403 100644
--- a/sshd-core/src/main/java/org/apache/sshd/SshServer.java
+++ b/sshd-core/src/main/java/org/apache/sshd/SshServer.java
@@ -62,6 +62,7 @@ import org.apache.sshd.common.file.nativefs.NativeFileSystemFactory;
 import org.apache.sshd.common.forward.DefaultTcpipForwarderFactory;
 import org.apache.sshd.common.forward.TcpipServerChannel;
 import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.SshFuture;
 import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.DefaultIoServiceFactoryFactory;
 import org.apache.sshd.common.io.IoAcceptor;
@@ -368,29 +369,32 @@ public class SshServer extends AbstractFactoryManager implements ServerFactoryMa
         start();
     }
 
-    public CloseFuture close(final boolean immediately) {
+    @Override
+    protected SshFuture<CloseFuture> doCloseGracefully() {
         stopSessionTimeoutListener();
         CloseFuture future;
         if (acceptor != null) {
-            future = CloseableUtils.sequential(acceptor, ioServiceFactory).close(immediately);
+            future = CloseableUtils.sequential(acceptor, ioServiceFactory).close(false);
         } else if (ioServiceFactory != null) {
-            future = ioServiceFactory.close(immediately);
+            future = ioServiceFactory.close(false);
         } else {
             future = CloseableUtils.closed();
         }
-        future.addListener(new SshFutureListener<CloseFuture>() {
-            public void operationComplete(CloseFuture future) {
-                acceptor = null;
-                ioServiceFactory = null;
-                if (shutdownExecutor && executor != null) {
-                    executor.shutdown();
-                    executor = null;
-                }
-            }
-        });
         return future;
     }
 
+    @Override
+    protected void doCloseImmediately() {
+        CloseableUtils.sequential(acceptor, ioServiceFactory).close(true);
+        acceptor = null;
+        ioServiceFactory = null;
+        if (shutdownExecutor && executor != null) {
+            executor.shutdown();
+            executor = null;
+        }
+        super.doCloseImmediately();
+    }
+
     /**
      * Obtain the list of active sessions.
      */

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java b/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
index f9d41a1..4f6a464 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/common/AgentForwardSupport.java
@@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory;
 /**
  * The server side fake agent, acting as an agent, but actually forwarding the requests to the auth channel on the client side.
  */
-public class AgentForwardSupport implements Closeable {
+public class AgentForwardSupport extends CloseableUtils.AbstractCloseable {
 
     private static final Logger log = LoggerFactory.getLogger(AgentForwardSupport.class);
 
@@ -67,8 +67,10 @@ public class AgentForwardSupport implements Closeable {
         }
     }
 
-    public CloseFuture close(boolean immediately) {
+    @Override
+    protected void doCloseImmediately() {
         close();
-        return CloseableUtils.closed();
+        super.doCloseImmediately();
     }
+
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
index 23c8ee6..dfdf288 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/local/ChannelAgentForwarding.java
@@ -90,8 +90,8 @@ public class ChannelAgentForwarding extends AbstractServerChannel {
     }
 
     public CloseFuture close(boolean immediately) {
-        return super.close(immediately).addListener(new SshFutureListener() {
-            public void operationComplete(SshFuture sshFuture) {
+        return super.close(immediately).addListener(new SshFutureListener<CloseFuture>() {
+            public void operationComplete(CloseFuture sshFuture) {
                 closeImmediately0();
             }
         });

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentForwardedChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentForwardedChannel.java b/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentForwardedChannel.java
index d9f5e6f..c57739c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentForwardedChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/unix/AgentForwardedChannel.java
@@ -66,9 +66,9 @@ public class AgentForwardedChannel extends AbstractClientChannel implements Runn
     }
 
     @Override
-    protected synchronized void postClose() {
+    protected synchronized void doCloseImmediately() {
         Socket.close(socket);
-        super.postClose();
+        super.doCloseImmediately();
     }
 
     protected synchronized void doWriteData(byte[] data, int off, int len) throws IOException {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwarding.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwarding.java b/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwarding.java
index 0887a1d..572c4d0 100644
--- a/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwarding.java
+++ b/sshd-core/src/main/java/org/apache/sshd/agent/unix/ChannelAgentForwarding.java
@@ -113,8 +113,8 @@ public class ChannelAgentForwarding extends AbstractServerChannel {
     }
 
     public CloseFuture close(boolean immediately) {
-        return super.close(immediately).addListener(new SshFutureListener() {
-            public void operationComplete(SshFuture sshFuture) {
+        return super.close(immediately).addListener(new SshFutureListener<CloseFuture>() {
+            public void operationComplete(CloseFuture sshFuture) {
                 closeImmediately0();
             }
         });

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
index 1fe7c02..37def96 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/AbstractClientChannel.java
@@ -128,7 +128,7 @@ public abstract class AbstractClientChannel extends AbstractChannel implements C
     }
 
     @Override
-    protected void postClose() {
+    protected void doCloseImmediately() {
         // Close inverted streams after
         // If the inverted stream is closed before, there's a small time window
         // in which we have:
@@ -137,7 +137,7 @@ public abstract class AbstractClientChannel extends AbstractChannel implements C
         // which leads to an IOException("Pipe closed") when reading.
         IoUtils.closeQuietly(in, out, err);
         IoUtils.closeQuietly(invertedIn, invertedOut, invertedErr);
-        super.postClose();
+        super.doCloseImmediately();
     }
 
     public int waitFor(int mask, long timeout) {
@@ -219,7 +219,7 @@ public abstract class AbstractClientChannel extends AbstractChannel implements C
         } catch (Exception e) {
             this.openFuture.setException(e);
             this.closeFuture.setClosed();
-            this.postClose();
+            this.doCloseImmediately();
         } finally {
             notifyStateChanged();
         }
@@ -234,7 +234,7 @@ public abstract class AbstractClientChannel extends AbstractChannel implements C
         this.openFailureMsg = msg;
         this.openFuture.setException(new SshException(msg));
         this.closeFuture.setClosed();
-        this.postClose();
+        this.doCloseImmediately();
         notifyStateChanged();
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java
index 87f4fbd..ac2b713 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/channel/ChannelSession.java
@@ -78,12 +78,12 @@ public class ChannelSession extends AbstractClientChannel {
     }
 
     @Override
-    protected void postClose() {
+    protected void doCloseImmediately() {
         if (streamPumper != null) {
             streamPumper.interrupt();
             streamPumper = null;
         }
-        super.postClose();
+        super.doCloseImmediately();
     }
 
     protected void pumpInputStream() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
index 78a28b2..a454874 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthService.java
@@ -23,22 +23,20 @@ import java.util.List;
 
 import org.apache.sshd.client.auth.deprecated.UserAuth;
 import org.apache.sshd.client.future.AuthFuture;
+import org.apache.sshd.common.Closeable;
 import org.apache.sshd.common.Service;
 import org.apache.sshd.common.ServiceFactory;
 import org.apache.sshd.common.Session;
-import org.apache.sshd.common.future.CloseFuture;
 import org.apache.sshd.common.future.DefaultCloseFuture;
 import org.apache.sshd.common.util.Buffer;
 import org.apache.sshd.common.util.CloseableUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 
 /**
  * Client side <code>ssh-auth</code> service.
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class ClientUserAuthService implements Service {
+public class ClientUserAuthService extends CloseableUtils.AbstractInnerCloseable implements Service {
 
     public static class Factory implements ServiceFactory {
 
@@ -51,13 +49,11 @@ public class ClientUserAuthService implements Service {
         }
     }
 
-    /** Our logger */
-    protected final Logger log = LoggerFactory.getLogger(getClass());
-
     protected final ClientSessionImpl session;
     protected ClientUserAuthServiceNew delegateNew;
     protected ClientUserAuthServiceOld delegateOld;
     protected boolean started;
+    protected DefaultCloseFuture future = new DefaultCloseFuture(null);
 
     public ClientUserAuthService(Session s) {
         if (!(s instanceof ClientSessionImpl)) {
@@ -89,13 +85,14 @@ public class ClientUserAuthService implements Service {
         }
     }
 
-    public CloseFuture close(boolean immediately) {
+    @Override
+    protected Closeable getInnerCloseable() {
         if (delegateNew != null) {
-            return delegateNew.close(immediately);
+            return delegateNew;
         } else if (delegateOld != null) {
-            return delegateOld.close(immediately);
+            return delegateOld;
         } else {
-            return CloseableUtils.closed();
+            return new CloseableUtils.AbstractCloseable() { };
         }
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceNew.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceNew.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceNew.java
index 1acd2ff..5616c0d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceNew.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceNew.java
@@ -50,10 +50,7 @@ import static org.apache.sshd.common.util.KeyUtils.getKeyType;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class ClientUserAuthServiceNew implements Service {
-
-    /** Our logger */
-    protected final Logger log = LoggerFactory.getLogger(getClass());
+public class ClientUserAuthServiceNew extends CloseableUtils.AbstractCloseable implements Service {
 
     /**
      * The AuthFuture that is being used by the current auth request.  This encodes the state.
@@ -216,12 +213,12 @@ public class ClientUserAuthServiceNew implements Service {
         }
     }
 
-    public CloseFuture close(boolean immediately) {
-        log.debug("Closing authentication service");
+    @Override
+    protected void preClose() {
+        super.preClose();
         if (!authFuture.isDone()) {
             authFuture.setException(new SshException("Session is closed"));
         }
-        return CloseableUtils.closed();
     }
 
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceOld.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceOld.java b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceOld.java
index 95b63b0..73518b4 100644
--- a/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceOld.java
+++ b/sshd-core/src/main/java/org/apache/sshd/client/session/ClientUserAuthServiceOld.java
@@ -40,7 +40,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class ClientUserAuthServiceOld implements Service {
+public class ClientUserAuthServiceOld extends CloseableUtils.AbstractCloseable implements Service {
 
     /** Our logger */
     protected final Logger log = LoggerFactory.getLogger(getClass());
@@ -168,12 +168,12 @@ public class ClientUserAuthServiceOld implements Service {
         }
     }
 
-    public CloseFuture close(boolean immediately) {
-        log.debug("Closing authentication service");
+    @Override
+    protected void preClose() {
+        super.preClose();
         if (!authFuture.isDone()) {
             authFuture.setException(new SshException("Session is closed"));
         }
-        return CloseableUtils.closed();
     }
 
     public AuthFuture auth(UserAuth userAuth) throws IOException {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
index dc412a7..e10f20c 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/AbstractFactoryManager.java
@@ -30,6 +30,7 @@ import org.apache.sshd.common.file.FileSystemFactory;
 import org.apache.sshd.common.io.IoServiceFactory;
 import org.apache.sshd.common.io.IoServiceFactoryFactory;
 import org.apache.sshd.common.session.ConnectionService;
+import org.apache.sshd.common.util.CloseableUtils;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -38,9 +39,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public abstract class AbstractFactoryManager implements FactoryManager {
-
-    protected final Logger log = LoggerFactory.getLogger(getClass());
+public abstract class AbstractFactoryManager extends CloseableUtils.AbstractCloseable implements FactoryManager {
 
     protected Map<String,String> properties = new HashMap<String,String>();
     protected IoServiceFactoryFactory ioServiceFactoryFactory;

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/Closeable.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/Closeable.java b/sshd-core/src/main/java/org/apache/sshd/common/Closeable.java
index 9c88fa6..ab98bdf 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/Closeable.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/Closeable.java
@@ -41,4 +41,17 @@ public interface Closeable {
      */
     CloseFuture close(boolean immediately);
 
+    /**
+     * Returns <code>true<</code> if this object has been closed.
+     */
+    boolean isClosed();
+
+    /**
+     * Returns <code>true</code> if the {@link #close(boolean)} method
+     * has been called.
+     * Note that this method will return <code>true</code> even if
+     * this {@link #isClosed()} returns <code>true</code>.
+     */
+    boolean isClosing();
+
 }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
index e275f06..2e333e2 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/channel/AbstractChannel.java
@@ -59,7 +59,7 @@ public abstract class AbstractChannel extends CloseableUtils.AbstractInnerClosea
     protected int recipient;
     protected volatile boolean eof;
     protected AtomicInteger gracefulState = new AtomicInteger();
-    private DefaultCloseFuture gracefulFuture = new DefaultCloseFuture(lock);
+    protected final DefaultCloseFuture gracefulFuture = new DefaultCloseFuture(lock);
     protected final List<RequestHandler<Channel>> handlers = new ArrayList<RequestHandler<Channel>>();
 
     public void addRequestHandler(RequestHandler<Channel> handler) {
@@ -149,6 +149,12 @@ public abstract class AbstractChannel extends CloseableUtils.AbstractInnerClosea
 
     protected Closeable getGracefulCloseable() {
         return new Closeable() {
+            public boolean isClosed() {
+                return gracefulFuture.isClosed();
+            }
+            public boolean isClosing() {
+                return true;
+            }
             public CloseFuture close(boolean immediately) {
                 if (!immediately) {
                     log.debug("Send SSH_MSG_CHANNEL_CLOSE on channel {}", AbstractChannel.this);
@@ -181,12 +187,14 @@ public abstract class AbstractChannel extends CloseableUtils.AbstractInnerClosea
         };
     }
 
+    @Override
     protected Closeable getInnerCloseable() {
         return getGracefulCloseable();
     }
 
-    protected void postClose() {
-        super.postClose();
+    @Override
+    protected void doCloseImmediately() {
+        super.doCloseImmediately();
         service.unregisterChannel(AbstractChannel.this);
     }
 

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
index 16b52d2..8c94d03 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/forward/DefaultTcpipForwarder.java
@@ -28,6 +28,7 @@ import java.util.Set;
 
 import org.apache.sshd.ClientChannel;
 import org.apache.sshd.client.future.OpenFuture;
+import org.apache.sshd.common.Closeable;
 import org.apache.sshd.common.ForwardingFilter;
 import org.apache.sshd.common.Session;
 import org.apache.sshd.common.SshConstants;
@@ -35,6 +36,7 @@ import org.apache.sshd.common.SshException;
 import org.apache.sshd.common.SshdSocketAddress;
 import org.apache.sshd.common.TcpipForwarder;
 import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.DefaultCloseFuture;
 import org.apache.sshd.common.future.SshFutureListener;
 import org.apache.sshd.common.io.IoAcceptor;
 import org.apache.sshd.common.io.IoHandler;
@@ -51,9 +53,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class DefaultTcpipForwarder implements TcpipForwarder, IoHandler {
-
-    private static final Logger LOGGER = LoggerFactory.getLogger(DefaultTcpipForwarder.class);
+public class DefaultTcpipForwarder extends CloseableUtils.AbstractInnerCloseable implements TcpipForwarder, IoHandler {
 
     private final ConnectionService service;
     private final Session session;
@@ -81,6 +81,12 @@ public class DefaultTcpipForwarder implements TcpipForwarder, IoHandler {
         if (local.getPort() < 0) {
             throw new IllegalArgumentException("Invalid local port: " + local.getPort());
         }
+        if (isClosed()) {
+            throw new IllegalStateException("TcpipForwarder is closed");
+        }
+        if (isClosing()) {
+            throw new IllegalStateException("TcpipForwarder is closing");
+        }
         SshdSocketAddress bound = doBind(local);
         localToRemote.put(bound.getPort(), remote);
         return bound;
@@ -146,36 +152,19 @@ public class DefaultTcpipForwarder implements TcpipForwarder, IoHandler {
         if (localForwards.remove(local) && acceptor != null) {
             acceptor.unbind(local.toInetSocketAddress());
             if (acceptor.getBoundAddresses().isEmpty()) {
-                close();
+                acceptor.close(true);
+                acceptor = null;
             }
         }
     }
 
-    public synchronized void initialize() {
-        if (this.acceptor == null) {
-            this.acceptor = session.getFactoryManager().getIoServiceFactory()
-                    .createAcceptor(this);
-        }
-    }
-
     public synchronized void close() {
-        if (acceptor != null) {
-            acceptor.dispose();
-            acceptor = null;
-        }
+        close(true);
     }
 
-    public CloseFuture close(boolean immediately) {
-        IoAcceptor a;
-        synchronized (this) {
-            a = acceptor;
-            acceptor = null;
-        }
-        if (a != null) {
-            return a.close(immediately);
-        } else {
-            return CloseableUtils.closed();
-        }
+    @Override
+    protected synchronized Closeable getInnerCloseable() {
+        return acceptor != null ? acceptor : new CloseableUtils.AbstractCloseable() { };
     }
 
     //
@@ -207,7 +196,7 @@ public class DefaultTcpipForwarder implements TcpipForwarder, IoHandler {
     public void sessionClosed(IoSession session) throws Exception {
         TcpipClientChannel channel = (TcpipClientChannel) session.getAttribute(TcpipClientChannel.class);
         if (channel != null) {
-            LOGGER.debug("IoSession {} closed, will now close the channel", session);
+            log.debug("IoSession {} closed, will now close the channel", session);
             channel.close(false);
         }
     }
@@ -231,7 +220,9 @@ public class DefaultTcpipForwarder implements TcpipForwarder, IoHandler {
     //
 
     private SshdSocketAddress doBind(SshdSocketAddress address) throws IOException {
-        initialize();
+        if (acceptor == null) {
+            acceptor = session.getFactoryManager().getIoServiceFactory().createAcceptor(this);
+        }
         Set<SocketAddress> before = acceptor.getBoundAddresses();
         try {
             acceptor.bind(address.toInetSocketAddress());

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
index 1ca0b19..6ec6eb3 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaService.java
@@ -62,6 +62,14 @@ public abstract class MinaService implements org.apache.sshd.common.io.IoService
         return CloseableUtils.closed();
     }
 
+    public boolean isClosed() {
+        return getIoService().isDisposed();
+    }
+
+    public boolean isClosing() {
+        return getIoService().isDisposing();
+    }
+
     public Map<Long, org.apache.sshd.common.io.IoSession> getManagedSessions() {
         Map<Long, IoSession> mina = new HashMap<Long, IoSession>(getIoService().getManagedSessions());
         Map<Long, org.apache.sshd.common.io.IoSession> sessions = new HashMap<Long, org.apache.sshd.common.io.IoSession>();

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
index 7e0b87b..268323f 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaServiceFactory.java
@@ -39,7 +39,7 @@ import org.slf4j.LoggerFactory;
 
 /**
  */
-public class MinaServiceFactory implements IoServiceFactory {
+public class MinaServiceFactory extends CloseableUtils.AbstractCloseable implements IoServiceFactory {
 
     private final Logger logger = LoggerFactory.getLogger(MinaServiceFactory.class);
     private final FactoryManager manager;
@@ -62,14 +62,16 @@ public class MinaServiceFactory implements IoServiceFactory {
         return new MinaAcceptor(manager, handler, ioProcessor);
     }
 
-    public CloseFuture close(boolean immediately) {
+    @Override
+    protected void doCloseImmediately() {
         try {
             executor.shutdownNow();
             executor.awaitTermination(5, TimeUnit.SECONDS);
         } catch (Exception e) {
-            logger.debug("Exception caught while closing executor", e);
+            log.debug("Exception caught while closing executor", e);
+        } finally {
+            super.doCloseImmediately();
         }
-        return CloseableUtils.closed();
     }
 
     public int getNioWorkers() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSession.java b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSession.java
index 0768f1a..d366fb6 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/mina/MinaSession.java
@@ -82,6 +82,12 @@ public class MinaSession extends CloseableUtils.AbstractInnerCloseable implement
     @Override
     protected Closeable getInnerCloseable() {
         return new Closeable() {
+            public boolean isClosing() {
+                return session.isClosing();
+            }
+            public boolean isClosed() {
+                return !session.isConnected();
+            }
             public org.apache.sshd.common.future.CloseFuture close(boolean immediately) {
                 final DefaultCloseFuture future = new DefaultCloseFuture(lock);
                 session.close(false).addListener(new IoFutureListener<IoFuture>() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
index 599b569..80a79b9 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Acceptor.java
@@ -95,7 +95,7 @@ public class Nio2Acceptor extends Nio2Service implements IoAcceptor {
         return super.close(immediately);
     }
 
-    public void doDispose() {
+    public void doCloseImmediately() {
         for (SocketAddress address : channels.keySet()) {
             try {
                 channels.get(address).close();
@@ -103,7 +103,7 @@ public class Nio2Acceptor extends Nio2Service implements IoAcceptor {
                 logger.debug("Exception caught while closing channel", e);
             }
         }
-        super.doDispose();
+        super.doCloseImmediately();
     }
 
     class AcceptCompletionHandler implements CompletionHandler<AsynchronousSocketChannel, SocketAddress> {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
index 1942b28..44019ec 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Service.java
@@ -26,6 +26,7 @@ import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.atomic.AtomicBoolean;
 
+import org.apache.sshd.common.Closeable;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.future.CloseFuture;
 import org.apache.sshd.common.future.SshFutureListener;
@@ -38,7 +39,7 @@ import org.slf4j.LoggerFactory;
 
 /**
  */
-public abstract class Nio2Service implements IoService {
+public abstract class Nio2Service extends CloseableUtils.AbstractInnerCloseable implements IoService {
 
     protected final Logger logger = LoggerFactory.getLogger(getClass());
     protected final FactoryManager manager;
@@ -63,18 +64,10 @@ public abstract class Nio2Service implements IoService {
         }
     }
 
-    protected void doDispose() {
-    }
-
-    public CloseFuture close(boolean immediately) {
+    @Override
+    protected Closeable getInnerCloseable() {
         List<IoSession> s = new ArrayList<IoSession>(sessions.values());
-        CloseFuture future = CloseableUtils.parallel(s).close(immediately);
-        future.addListener(new SshFutureListener<CloseFuture>() {
-            public void operationComplete(CloseFuture future) {
-                doDispose();
-            }
-        });
-        return future;
+        return CloseableUtils.parallel(s);
     }
 
     public Map<Long, IoSession> getManagedSessions() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
index 46713e0..07eb627 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2ServiceFactory.java
@@ -28,6 +28,7 @@ import java.util.concurrent.TimeUnit;
 import org.apache.sshd.common.FactoryManager;
 import org.apache.sshd.common.RuntimeSshException;
 import org.apache.sshd.common.future.CloseFuture;
+import org.apache.sshd.common.future.SshFuture;
 import org.apache.sshd.common.io.IoAcceptor;
 import org.apache.sshd.common.io.IoConnector;
 import org.apache.sshd.common.io.IoHandler;
@@ -38,9 +39,8 @@ import org.slf4j.LoggerFactory;
 
 /**
  */
-public class Nio2ServiceFactory implements IoServiceFactory {
+public class Nio2ServiceFactory extends CloseableUtils.AbstractCloseable implements IoServiceFactory {
 
-    private final Logger logger = LoggerFactory.getLogger(Nio2ServiceFactory.class);
     private final FactoryManager manager;
     private final AsynchronousChannelGroup group;
 
@@ -63,14 +63,16 @@ public class Nio2ServiceFactory implements IoServiceFactory {
         return new Nio2Acceptor(manager, handler, group);
     }
 
-    public CloseFuture close(boolean immediately) {
+    @Override
+    protected void doCloseImmediately() {
         try {
             group.shutdownNow();
             group.awaitTermination(5, TimeUnit.SECONDS);
         } catch (Exception e) {
-            logger.debug("Exception caught while closing channel group", e);
+            log.debug("Exception caught while closing channel group", e);
+        } finally {
+            super.doCloseImmediately();
         }
-        return CloseableUtils.closed();
     }
 
     public int getNioWorkers() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
index d1fe7cb..c044815 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/io/nio2/Nio2Session.java
@@ -31,6 +31,7 @@ import java.util.concurrent.LinkedTransferQueue;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
 
+import org.apache.sshd.common.future.CloseFuture;
 import org.apache.sshd.common.future.DefaultSshFuture;
 import org.apache.sshd.common.future.SshFuture;
 import org.apache.sshd.common.io.IoHandler;
@@ -132,7 +133,7 @@ public class Nio2Session extends CloseableUtils.AbstractCloseable implements IoS
     }
 
     @Override
-    protected SshFuture doCloseGracefully() {
+    protected CloseFuture doCloseGracefully() {
         synchronized (writes) {
             return CloseableUtils.parallel(writes.toArray(new SshFuture[writes.size()]));
         }
@@ -154,15 +155,13 @@ public class Nio2Session extends CloseableUtils.AbstractCloseable implements IoS
             log.info("Exception caught while closing socket", e);
         }
         service.sessionClosed(this);
-        closeFuture.setClosed();
-        state.set(CLOSED);
+        super.doCloseImmediately();
         try {
             handler.sessionClosed(this);
         } catch (Exception e) {
             // Ignore
             log.debug("Exception caught while calling IoHandler#sessionClosed", e);
         }
-        log.debug("{} closed", this);
     }
 
     public IoService getService() {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
index e2933bf..ee25cef 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/session/AbstractSession.java
@@ -436,13 +436,15 @@ public abstract class AbstractSession extends CloseableUtils.AbstractInnerClosea
         close(true);
     }
 
+    @Override
     protected Closeable getInnerCloseable() {
         return CloseableUtils.sequential(lock,
                 CloseableUtils.parallel(lock, getServices()), ioSession);
     }
 
-    protected void postClose() {
-        super.postClose();
+    @Override
+    protected void doCloseImmediately() {
+        super.doCloseImmediately();
         // Fire 'close' event
         final ArrayList<SessionListener> l = new ArrayList<SessionListener>(listeners);
         for (SessionListener sl : l) {

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/common/util/CloseableUtils.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/common/util/CloseableUtils.java b/sshd-core/src/main/java/org/apache/sshd/common/util/CloseableUtils.java
index 2393d72..2ae71c9 100644
--- a/sshd-core/src/main/java/org/apache/sshd/common/util/CloseableUtils.java
+++ b/sshd-core/src/main/java/org/apache/sshd/common/util/CloseableUtils.java
@@ -59,30 +59,60 @@ public class CloseableUtils {
     }
 
     public static Closeable parallel(final Object lock, final Closeable... closeables) {
-        if (closeables.length == 0) {
+        int nbNonNulls = 0;
+        for (Closeable closeable : closeables) {
+            if (closeable != null) {
+                nbNonNulls++;
+            }
+        }
+        if (nbNonNulls == 0) {
             return new Closeable() {
+                final CloseFuture future = new DefaultCloseFuture(lock);
+                public boolean isClosed() {
+                    return future.isClosed();
+                }
+                public boolean isClosing() {
+                    return isClosed();
+                }
                 public CloseFuture close(boolean immediately) {
-                    final CloseFuture future = new DefaultCloseFuture(lock);
                     future.setClosed();
                     return future;
                 }
             };
-        } else if (closeables.length == 1) {
-            return closeables[0];
+        } else if (nbNonNulls == 1) {
+            for (Closeable closeable : closeables) {
+                if (closeable != null) {
+                    return closeable;
+                }
+            }
+            throw new IllegalStateException();
         } else {
             return new Closeable() {
+                final CloseFuture future = new DefaultCloseFuture(lock);
+                final AtomicBoolean closing = new AtomicBoolean();
+                public boolean isClosed() {
+                    return future.isClosed();
+                }
+                public boolean isClosing() {
+                    return closing.get();
+                }
                 public CloseFuture close(boolean immediately) {
-                    final CloseFuture future = new DefaultCloseFuture(lock);
                     final AtomicInteger count = new AtomicInteger(closeables.length);
-                    SshFutureListener<CloseFuture> listener = new SshFutureListener<CloseFuture>() {
-                        public void operationComplete(CloseFuture f) {
-                            if (count.decrementAndGet() == 0) {
-                                future.setClosed();
+                    if (closing.compareAndSet(false, true)) {
+                        SshFutureListener<CloseFuture> listener = new SshFutureListener<CloseFuture>() {
+                            public void operationComplete(CloseFuture f) {
+                                if (count.decrementAndGet() == 0) {
+                                    future.setClosed();
+                                }
+                            }
+                        };
+                        for (Closeable c : closeables) {
+                            if (c != null) {
+                                c.close(immediately).addListener(listener);
+                            } else {
+                                listener.operationComplete(null);
                             }
                         }
-                    };
-                    for (Closeable c : closeables) {
-                        c.close(immediately).addListener(listener);
                     }
                     return future;
                 }
@@ -103,61 +133,91 @@ public class CloseableUtils {
     }
 
     public static Closeable sequential(final Object lock, final Closeable... closeables) {
-        if (closeables.length == 0) {
+        int nbNonNulls = 0;
+        for (Closeable closeable : closeables) {
+            if (closeable != null) {
+                nbNonNulls++;
+            }
+        }
+        if (nbNonNulls == 0) {
             return new Closeable() {
+                final CloseFuture future = new DefaultCloseFuture(lock);
+                public boolean isClosed() {
+                    return future.isClosed();
+                }
+                public boolean isClosing() {
+                    return isClosed();
+                }
                 public CloseFuture close(boolean immediately) {
-                    final CloseFuture future = new DefaultCloseFuture(lock);
                     future.setClosed();
                     return future;
                 }
             };
-        } else if (closeables.length == 1) {
-            return closeables[0];
+        } else if (nbNonNulls == 1) {
+            for (Closeable closeable : closeables) {
+                if (closeable != null) {
+                    return closeable;
+                }
+            }
+            throw new IllegalStateException();
         } else {
             return new Closeable() {
+                final DefaultCloseFuture future = new DefaultCloseFuture(lock);
+                final AtomicBoolean closing = new AtomicBoolean();
+                public boolean isClosed() {
+                    return future.isClosed();
+                }
+                public boolean isClosing() {
+                    return closing.get();
+                }
                 public CloseFuture close(final boolean immediately) {
-                    final DefaultCloseFuture future = new DefaultCloseFuture(lock);
-                    final Iterator<Closeable> iterator = Arrays.asList(closeables).iterator();
-                    SshFutureListener<CloseFuture> listener = new SshFutureListener<CloseFuture>() {
-                        public void operationComplete(CloseFuture previousFuture) {
-                            if (iterator.hasNext()) {
-                                Closeable c = iterator.next();
-                                CloseFuture nextFuture = c.close(immediately);
-                                nextFuture.addListener(this);
-                            } else {
-                                future.setClosed();
+                    if (closing.compareAndSet(false, true)) {
+                        final Iterator<Closeable> iterator = Arrays.asList(closeables).iterator();
+                        SshFutureListener<CloseFuture> listener = new SshFutureListener<CloseFuture>() {
+                            public void operationComplete(CloseFuture previousFuture) {
+                                while (iterator.hasNext()) {
+                                    Closeable c = iterator.next();
+                                    if (c != null) {
+                                        CloseFuture nextFuture = c.close(immediately);
+                                        nextFuture.addListener(this);
+                                        return;
+                                    }
+                                }
+                                if (!iterator.hasNext()) {
+                                    future.setClosed();
+                                }
                             }
-                        }
-                    };
-                    listener.operationComplete(null);
+                        };
+                        listener.operationComplete(null);
+                    }
                     return future;
                 }
             };
         }
     }
 
-    public static SshFuture parallel(final SshFuture... futures) {
-        if (futures.length == 0) {
-            final DefaultSshFuture<SshFuture> future = new DefaultSshFuture<SshFuture>(null);
-            future.setValue(true);
-            return future;
-        } else if (futures.length == 1) {
-            return futures[0];
-        } else {
-            final CloseFuture future = new DefaultCloseFuture(null);
+    public static <T extends SshFuture> CloseFuture parallel(final SshFuture<T>... futures) {
+        final CloseFuture future = new DefaultCloseFuture(null);
+        if (futures.length > 0) {
             final AtomicInteger count = new AtomicInteger(futures.length);
-            SshFutureListener<?> listener = new SshFutureListener<SshFuture>() {
-                public void operationComplete(SshFuture f) {
+            SshFutureListener<T> listener = new SshFutureListener<T>() {
+                public void operationComplete(T f) {
                     if (count.decrementAndGet() == 0) {
                         future.setClosed();
                     }
                 }
             };
-            for (SshFuture f : futures) {
-                f.addListener(listener);
+            for (SshFuture<T> f : futures) {
+                if (f != null) {
+                    f.addListener(listener);
+                } else {
+                    listener.operationComplete(null);
+                }
             }
-            return future;
+        } else {
+            future.setClosed();
         }
+        return future;
     }
 
     public static abstract class AbstractCloseable implements Closeable {
@@ -172,33 +232,38 @@ public class CloseableUtils {
         /** Lock object for this session state */
         protected final Object lock = new Object();
         /** State of this object */
-        protected final AtomicInteger state = new AtomicInteger();
+        protected final AtomicInteger state = new AtomicInteger(OPENED);
         /** A future that will be set 'closed' when the object is actually closed */
         protected final CloseFuture closeFuture = new DefaultCloseFuture(lock);
 
         public CloseFuture close(boolean immediately) {
             if (immediately) {
-                if (state.compareAndSet(0, IMMEDIATE) || state.compareAndSet(GRACEFUL, IMMEDIATE)) {
+                if (state.compareAndSet(OPENED, IMMEDIATE) || state.compareAndSet(GRACEFUL, IMMEDIATE)) {
                     log.debug("Closing {} immediately", this);
+                    preClose();
                     doCloseImmediately();
+                    log.debug("{} closed", this);
                 } else {
                     log.debug("{} is already {}", this, state.get() == CLOSED ? "closed" : "closing");
                 }
             } else {
-                if (state.compareAndSet(0, GRACEFUL)) {
+                if (state.compareAndSet(OPENED, GRACEFUL)) {
                     log.debug("Closing {} gracefully", this);
-                    SshFuture grace = doCloseGracefully();
+                    preClose();
+                    SshFuture<CloseFuture> grace = doCloseGracefully();
                     if (grace != null) {
-                        grace.addListener(new SshFutureListener() {
-                            public void operationComplete(SshFuture future) {
+                        grace.addListener(new SshFutureListener<CloseFuture>() {
+                            public void operationComplete(CloseFuture future) {
                                 if (state.compareAndSet(GRACEFUL, IMMEDIATE)) {
                                     doCloseImmediately();
+                                    log.debug("{} closed", this);
                                 }
                             }
                         });
                     } else {
                         if (state.compareAndSet(GRACEFUL, IMMEDIATE)) {
                             doCloseImmediately();
+                            log.debug("{} closed", this);
                         }
                     }
                 } else {
@@ -208,19 +273,26 @@ public class CloseableUtils {
             return closeFuture;
         }
 
-        protected SshFuture doCloseGracefully() {
-            return null;
+        public boolean isClosed() {
+            return state.get() == CLOSED;
         }
 
-        protected void doCloseImmediately() {
-            postClose();
+        public boolean isClosing() {
+            return state.get() != OPENED;
+        }
+
+        protected void preClose() {
         }
 
-        protected void postClose() {
+        protected SshFuture<CloseFuture> doCloseGracefully() {
+            return null;
+        }
+
+        protected void doCloseImmediately() {
             closeFuture.setClosed();
             state.set(CLOSED);
-            log.debug("{} closed", this);
         }
+
     }
 
     public static abstract class AbstractInnerCloseable extends AbstractCloseable {
@@ -228,7 +300,7 @@ public class CloseableUtils {
         protected abstract Closeable getInnerCloseable();
 
         @Override
-        protected SshFuture doCloseGracefully() {
+        protected SshFuture<CloseFuture> doCloseGracefully() {
             return getInnerCloseable().close(false);
         }
 
@@ -236,7 +308,7 @@ public class CloseableUtils {
         protected void doCloseImmediately() {
             getInnerCloseable().close(true).addListener(new SshFutureListener<CloseFuture>() {
                 public void operationComplete(CloseFuture future) {
-                    postClose();
+                    AbstractInnerCloseable.super.doCloseImmediately();
                 }
             });
         }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
index cbe21f7..5866a59 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/channel/ChannelSession.java
@@ -192,6 +192,12 @@ public class ChannelSession extends AbstractServerChannel {
 
     protected Closeable getCommandCloseable() {
         return new Closeable() {
+            public boolean isClosed() {
+                return commandExitFuture.isClosed();
+            }
+            public boolean isClosing() {
+                return isClosed();
+            }
             public CloseFuture close(boolean immediately) {
                 if (immediately) {
                     commandExitFuture.setClosed();
@@ -225,14 +231,14 @@ public class ChannelSession extends AbstractServerChannel {
         };
     }
     @Override
-    protected void postClose() {
+    protected void doCloseImmediately() {
         if (command != null) {
             command.destroy();
             command = null;
         }
         remoteWindow.notifyClosed();
         IoUtils.closeQuietly(out, err, receiver);
-        super.postClose();
+        super.doCloseImmediately();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
index 341985a..1d7ea3d 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/session/ServerUserAuthService.java
@@ -43,7 +43,7 @@ import org.slf4j.LoggerFactory;
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class ServerUserAuthService implements Service {
+public class ServerUserAuthService extends CloseableUtils.AbstractCloseable implements Service {
 
     public static class Factory implements ServiceFactory {
 
@@ -56,7 +56,6 @@ public class ServerUserAuthService implements Service {
         }
     }
 
-    private final Logger log = LoggerFactory.getLogger(getClass());
     private final ServerSession session;
     private List<NamedFactory<UserAuth>> userAuthFactories;
     private List<List<String>> authMethods;
@@ -252,11 +251,6 @@ public class ServerUserAuthService implements Service {
         }
     }
 
-    public CloseFuture close(boolean immediately) {
-        log.debug("Closing authentication service");
-        return CloseableUtils.closed();
-    }
-
     private ServerFactoryManager getFactoryManager() {
         return session.getFactoryManager();
     }

http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/569fac2a/sshd-core/src/main/java/org/apache/sshd/server/x11/X11ForwardSupport.java
----------------------------------------------------------------------
diff --git a/sshd-core/src/main/java/org/apache/sshd/server/x11/X11ForwardSupport.java b/sshd-core/src/main/java/org/apache/sshd/server/x11/X11ForwardSupport.java
index 8ab57a2..047d207 100644
--- a/sshd-core/src/main/java/org/apache/sshd/server/x11/X11ForwardSupport.java
+++ b/sshd-core/src/main/java/org/apache/sshd/server/x11/X11ForwardSupport.java
@@ -43,7 +43,7 @@ import org.slf4j.LoggerFactory;
 /**
  * @author <a href="mailto:dev@mina.apache.org">Apache MINA SSHD Project</a>
  */
-public class X11ForwardSupport implements IoHandler, Closeable {
+public class X11ForwardSupport extends CloseableUtils.AbstractInnerCloseable implements IoHandler, Closeable {
 
     private static String xauthCommand = System.getProperty("sshd.xauthCommand", "xauth");
 
@@ -55,8 +55,6 @@ public class X11ForwardSupport implements IoHandler, Closeable {
      */
     public static final String ENV_DISPLAY = "DISPLAY";
 
-    protected final Logger log = LoggerFactory.getLogger(getClass());
-
     private final ConnectionService service;
     private IoAcceptor acceptor;
 
@@ -65,18 +63,13 @@ public class X11ForwardSupport implements IoHandler, Closeable {
         this.service = service;
     }
 
-    public synchronized void initialize() {
-        if (this.acceptor == null) {
-            this.acceptor = service.getSession().getFactoryManager().getIoServiceFactory()
-                    .createAcceptor(this);
-        }
+    public void close() {
+        close(true);
     }
 
-    public synchronized void close() {
-        if (acceptor != null) {
-            acceptor.dispose();
-            acceptor = null;
-        }
+    @Override
+    protected Closeable getInnerCloseable() {
+        return acceptor != null ? acceptor : new CloseableUtils.AbstractCloseable() { };
     }
 
     public CloseFuture close(boolean immediately) {
@@ -96,7 +89,16 @@ public class X11ForwardSupport implements IoHandler, Closeable {
                                              String authenticationProtocol, String authenticationCookie,
                                              int screen) throws IOException {
 
-        initialize();
+        if (isClosed()) {
+            throw new IllegalStateException("X11ForwardSupport is closed");
+        }
+        if (isClosing()) {
+            throw new IllegalStateException("X11ForwardSupport is closing");
+        }
+
+        if (acceptor == null) {
+            acceptor = service.getSession().getFactoryManager().getIoServiceFactory().createAcceptor(this);
+        }
 
         int displayNumber, port;
         InetSocketAddress addr = null;