You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by lg...@apache.org on 2021/03/05 09:17:56 UTC

[mina-sshd] 03/03: [SSHD-1125] Added option to require immediate close of channel in command ExitCallback invocation

This is an automated email from the ASF dual-hosted git repository.

lgoldstein pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/mina-sshd.git

commit e88c1a769dbb0a10ba9be3c9c0bd54c2eda3737f
Author: Lyor Goldstein <lg...@apache.org>
AuthorDate: Fri Feb 26 06:54:43 2021 +0200

    [SSHD-1125] Added option to require immediate close of channel in command ExitCallback invocation
---
 CHANGES.md                                         |  5 ++--
 .../java/org/apache/sshd/server/ExitCallback.java  | 27 ++++++++++++++++++++--
 .../apache/sshd/server/channel/ChannelSession.java | 10 ++++----
 .../apache/sshd/util/test/BogusExitCallback.java   | 12 +++++++---
 .../org/apache/sshd/sftp/server/SftpSubsystem.java |  4 +++-
 5 files changed, 45 insertions(+), 13 deletions(-)

diff --git a/CHANGES.md b/CHANGES.md
index 4bf9e41..942ed01 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -16,13 +16,14 @@
 
 ## Minor code helpers
 
+* [SSHD-525](https://issues.apache.org/jira/browse/SSHD-525) Added support for SFTP **client-side** ["posix-rename@openssh.com"
+ extension](http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=1.28&content-type=text/x-cvsweb-markup) - see section 3.3
 * [SSHD-1085](https://issues.apache.org/jira/browse/SSHD-1085) Added `CliLogger` + more verbosity on `SshClientMain`
 * [SSHD-1109](https://issues.apache.org/jira/browse/SSHD-1109) Route tests JUL logging via SLF4JBridgeHandler
 * [SSHD-1109](https://issues.apache.org/jira/browse/SSHD-1109) Provide full slf4j logger capabilities to CliLogger + use it in all CLI classes
 * [SSHD-1110](https://issues.apache.org/jira/browse/SSHD-1110) Replace `Class#newInstance()` calls with `Class#getDefaultConstructor().newInstance()`
 * [SSHD-1111](https://issues.apache.org/jira/browse/SSHD-1111) Fixed SshClientCliSupport compression option detection
-* [SSHD-525](https://issues.apache.org/jira/browse/SSHD-525) Added support for SFTP **client-side** ["posix-rename@openssh.com"
- extension](http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.bin/ssh/PROTOCOL?rev=1.28&content-type=text/x-cvsweb-markup) - see section 3.3
+* [SSHD-1125](https://issues.apache.org/jira/browse/SSHD-1125) Added option to require immediate close of channel in command `ExitCallback` invocation
 * [SSHD-1127](https://issues.apache.org/jira/browse/SSHD-1127) Consolidated `SftpSubsystem` support implementations into `SftpSubsystemConfigurator`
 
 ## Behavioral changes and enhancements
diff --git a/sshd-common/src/main/java/org/apache/sshd/server/ExitCallback.java b/sshd-common/src/main/java/org/apache/sshd/server/ExitCallback.java
index dfa55be..eb1bca1 100644
--- a/sshd-common/src/main/java/org/apache/sshd/server/ExitCallback.java
+++ b/sshd-common/src/main/java/org/apache/sshd/server/ExitCallback.java
@@ -30,7 +30,17 @@ public interface ExitCallback {
      * @param exitValue the exit value
      */
     default void onExit(int exitValue) {
-        onExit(exitValue, "");
+        onExit(exitValue, false);
+    }
+
+    /**
+     * Informs the SSH server that the shell has exited
+     *
+     * @param exitValue        the exit value
+     * @param closeImmediately whether to also terminate the channel immediately or do a graceful close.
+     */
+    default void onExit(int exitValue, boolean closeImmediately) {
+        onExit(exitValue, "", closeImmediately);
     }
 
     /**
@@ -39,5 +49,18 @@ public interface ExitCallback {
      * @param exitValue   the exit value
      * @param exitMessage exit value description
      */
-    void onExit(int exitValue, String exitMessage);
+    default void onExit(int exitValue, String exitMessage) {
+        onExit(exitValue, exitMessage, false);
+    }
+
+    /**
+     *
+     * Informs the SSH client/server that the shell has exited
+     *
+     * @param exitValue        the exit value
+     * @param exitMessage      exit value description
+     * @param closeImmediately whether to also terminate the channel immediately or do a graceful close.
+     */
+    void onExit(int exitValue, String exitMessage, boolean closeImmediately);
+
 }
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 cfd3dad..86b4bbf 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
@@ -771,9 +771,9 @@ public class ChannelSession extends AbstractServerChannel {
             doWriteExtendedData(buffer.array(), buffer.rpos(), buffer.available());
         }
 
-        command.setExitCallback((exitValue, exitMessage) -> {
+        command.setExitCallback((exitValue, exitMessage, closeImmediately) -> {
             try {
-                closeShell(exitValue);
+                closeShell(exitValue, closeImmediately);
                 if (log.isDebugEnabled()) {
                     log.debug("onExit({}) code={} message='{}' shell closed",
                             ChannelSession.this, exitValue, exitMessage);
@@ -898,9 +898,9 @@ public class ChannelSession extends AbstractServerChannel {
         return env;
     }
 
-    protected void closeShell(int exitValue) throws IOException {
+    protected void closeShell(int exitValue, boolean closeImmediately) throws IOException {
         if (log.isDebugEnabled()) {
-            log.debug("closeShell({}) exit code={}", this, exitValue);
+            log.debug("closeShell({}) exit code={}, immediate={}", this, exitValue, closeImmediately);
         }
 
         if (!isClosing()) {
@@ -910,7 +910,7 @@ public class ChannelSession extends AbstractServerChannel {
             sendEof();
             sendExitStatus(exitValue);
             commandExitFuture.setClosed();
-            close(false);
+            close(closeImmediately);
         } else {
             commandExitFuture.setClosed();
         }
diff --git a/sshd-core/src/test/java/org/apache/sshd/util/test/BogusExitCallback.java b/sshd-core/src/test/java/org/apache/sshd/util/test/BogusExitCallback.java
index a4f1ff6..9de602a 100644
--- a/sshd-core/src/test/java/org/apache/sshd/util/test/BogusExitCallback.java
+++ b/sshd-core/src/test/java/org/apache/sshd/util/test/BogusExitCallback.java
@@ -25,21 +25,23 @@ public class BogusExitCallback implements ExitCallback {
     private boolean exited;
     private int exitValue;
     private String exitMessage;
+    private boolean closeImmediately;
 
     public BogusExitCallback() {
         super();
     }
 
     @Override
-    public void onExit(int exitValue) {
-        onExit(exitValue, String.valueOf(exitValue));
+    public void onExit(int exitValue, boolean closeImmediately) {
+        onExit(exitValue, String.valueOf(exitValue), closeImmediately);
     }
 
     @Override
-    public void onExit(int exitValue, String exitMessage) {
+    public void onExit(int exitValue, String exitMessage, boolean closeImmediately) {
         this.exited = true;
         this.exitValue = exitValue;
         this.exitMessage = exitMessage;
+        this.closeImmediately = closeImmediately;
     }
 
     public boolean isExited() {
@@ -53,4 +55,8 @@ public class BogusExitCallback implements ExitCallback {
     public String getExitMessage() {
         return exitMessage;
     }
+
+    public boolean isCloseImmediately() {
+        return closeImmediately;
+    }
 }
diff --git a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/SftpSubsystem.java b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/SftpSubsystem.java
index 2c79d23..03c8936 100644
--- a/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/SftpSubsystem.java
+++ b/sshd-sftp/src/main/java/org/apache/sshd/sftp/server/SftpSubsystem.java
@@ -289,6 +289,7 @@ public class SftpSubsystem
 
     @Override
     public void run() {
+        int exitCode = 0;
         try {
             while (true) {
                 Buffer buffer = requests.take();
@@ -305,10 +306,11 @@ public class SftpSubsystem
                 Session session = getServerSession();
                 error("run({}) {} caught in SFTP subsystem: {}",
                         session, t.getClass().getSimpleName(), t.getMessage(), t);
+                exitCode = -1;
             }
         } finally {
             closeAllHandles();
-            callback.onExit(0);
+            callback.onExit(exitCode, exitCode != 0);
         }
     }