Repository: mina-sshd Updated Branches: refs/heads/master 644649975 -> a4bb50233
[SSHD-835] Further clarified documentation regarding usage of CloseableExecutorService(s) Project: http://git-wip-us.apache.org/repos/asf/mina-sshd/repo Commit: http://git-wip-us.apache.org/repos/asf/mina-sshd/commit/a4bb5023 Tree: http://git-wip-us.apache.org/repos/asf/mina-sshd/tree/a4bb5023 Diff: http://git-wip-us.apache.org/repos/asf/mina-sshd/diff/a4bb5023 Branch: refs/heads/master Commit: a4bb502333ea96755e79fef850235b26d6aafb81 Parents: 1e29158 Author: Goldstein Lyor <[email protected]> Authored: Thu Jul 26 08:00:58 2018 +0300 Committer: Goldstein Lyor <[email protected]> Committed: Thu Jul 26 08:04:30 2018 +0300 ---------------------------------------------------------------------- README.md | 37 +++++++++++++++++++++++++++++-------- 1 file changed, 29 insertions(+), 8 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mina-sshd/blob/a4bb5023/README.md ---------------------------------------------------------------------- diff --git a/README.md b/README.md index b718b16..a44b48d 100644 --- a/README.md +++ b/README.md @@ -409,28 +409,49 @@ be tailored to present different views for different clients ## `ExecutorService`-s The framework requires from time to time spawning some threads in order to function correctly - e.g., commands, SFTP subsystem, -port forwarding (among others) require such support. By default, the framework will allocate an [ExecutorService](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html) for each specific purpose and then shut it down when the module has completed its work - e.g., session -was closed. Note that SSHD uses the `CloseableExecutorService` interface instead of the usual `ExecutorService` in order to provide graceful shutdown. -Users may provide their own `CloseableExecutorService`(s) instead of the internally auto-allocated ones - e.g., in -order to control the max. spawned threads, stack size, track threads, etc... but they can leverage the `ThreadUtils.ThreadPoolExecutor` implementation which should cover most use cases. -If a single executor is shared between several services, it needs to be wrapped with the `ThreadUtils.noClose(executor)` method. +port forwarding (among others) require such support. By default, the framework will allocate an [ExecutorService](https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ExecutorService.html) +for each specific purpose and then shut it down when the module has completed its work - e.g., session was closed. Note that +SSHD uses the `CloseableExecutorService` interface instead of the usual `ExecutorService` in order to provide graceful shutdown. +Users may provide their own `CloseableExecutorService`(s) instead of the internally auto-allocated ones - e.g., in order to +control the max. spawned threads, stack size, track threads, etc... but they can leverage the `SshThreadPoolExecutor` implementation +which should cover most use cases. + +Users who want to provide their own `ExecutorService` and not use `SshThreadPoolExecutor` should wrap it as a `NoCloseExecutor` +and take care of shutting it down when SSHD is done with (provided, of course, that the user's own code does not need it to +remain active afterwards...). ```java /* - * An example for SFTP - there are other such locations. By default, - * the SftpSubsystem implementation creates a single-threaded executor + * An example user-provided executor service for SFTP - there are other such locations. + * By default, the SftpSubsystem implementation creates a single-threaded executor * for each session, uses it to spawn the SFTP command handler and shuts * it down when the command is destroyed */ SftpSubsystemFactory factory = new SftpSubsystemFactory.Builder() - .withExecutorService(ThreadUtils.noClose(mySuperDuperExecutorService)) + .withExecutorService(new NoCloseExecutor(mySuperDuperExecutorService)) .build(); SshServer sshd = SshServer.setupDefaultServer(); sshd.setSubsystemFactories(Collections.<NamedFactory<Command>>singletonList(factory)); ``` +If a single `CloseableExecutorService` is shared between several services, it needs to be wrapped with the +`ThreadUtils.noClose(executor)` method. + +```java + CloseableExecutorService sharedService = ...obtain/create an instance...; + + SftpSubsystemFactory factory = new SftpSubsystemFactory.Builder() + .withExecutorService(ThreadUtils.noClose(sharedService)) + .build(); + + ChannelAgentForwarding forward = new ChannelAgentForwarding(ThreadUtils.noClose(sharedService)); +``` + +**Note:** Do not share the instance returned by `ThreadUtils.noClose` between services as it interferes with +the graceful closing mechanism. Use a new wrapper instance for each service. + ## Remote command execution All command execution - be it shell or single command - boils down to a `Command` instance being created, initialized and then
