[
https://issues.apache.org/jira/browse/SSHD-1070?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17191631#comment-17191631
]
Feng Jiajie commented on SSHD-1070:
-----------------------------------
Hi [~wolft] Thanks for the reply.
The whole story goes like that:
# I need to use ssh -R (remote port forwarding), and then I met the problem
described by SSHD-1069.
# I found SSHD-1003 and SSHD-557, they solved the ssh -L (local port
forwarding) problem (before SSHD-1003, ssh -L had the same problem, see
SSHD-557).
# SSHD-1003 modified TcpipServerChannel, So I modified the TcpipClientChannel
in the same way to solve the -R problem.
https://github.com/fengjiajie/mina-sshd/commit/a448cae1ca6b68a08b34e8d375fb56114561b144
. The OOM occurred while testing the new code.
# I think -L might have the same OOM problem, then I created SSHD-1070.
The whole thing started with resolving the SSHD-1069 deadlock, so when I see
BlockingQueue, I have the above question.
{quote}I think it should not, since a {{put()}} that succeeds then executes in
the same thread {{startWriting()}}, and {{startWriting()}} calls itself once a
buffered element has been written to process the rest of the queue. So
eventually there should be space again, and a pending {{put()}} should then
succeed.
{quote}
I don't really have a good understanding of the SSHD processing process and
present an idea that may not be correct:
Consider a scenario, if there is only one thread, and BlockingQueue max size is
small, eg 1. startWriting doesn't actually output data, but instead calls nio's
future write. If the next scheduling still reads the data instead of output
data, the queue would be full. So when the maximum length of the queue is
larger, the probability of deadlock is lower, but it's still possible?
I think maybe we could handle this situation closer to the network layer. For
example, if it is found that it is not suitable to read data from Channel (e.g.
the queue in the program is full), then do not read the data first. For
example, if the *Nio2CompletionHandler handleReadCycleCompletion* finds that
the queue is full, then *doReadCycle* is no longer called, and if the thread
executing the output operation finds that doReadCycle was not called, then
doReadCycle is called by that thread, blocking the data outside of the JVM.
> OutOfMemoryError when use port forwarding
> -----------------------------------------
>
> Key: SSHD-1070
> URL: https://issues.apache.org/jira/browse/SSHD-1070
> Project: MINA SSHD
> Issue Type: Bug
> Affects Versions: 2.5.1
> Reporter: Feng Jiajie
> Priority: Major
> Time Spent: 20m
> Remaining Estimate: 0h
>
> Hi [~gnodet], I found this commit implemented asynchronous port forwarding:
> [https://github.com/apache/mina-sshd/commit/45f84aab59b2e11d72942cffe9d810e37ab64959#diff-33823b8546f71d77bb1d653358ecde70]
> However, when a large amount of data is returned from upstream application,
> it is possible to cause an OOM in SSHD.
> Step1. SSHD server:
> {code:java}
> import org.apache.sshd.common.FactoryManager;
> import org.apache.sshd.common.PropertyResolverUtils;
> import org.apache.sshd.common.util.security.SecurityUtils;
> import org.apache.sshd.server.SshServer;
> import org.apache.sshd.server.forward.AcceptAllForwardingFilter;
> import org.apache.sshd.server.keyprovider.SimpleGeneratorHostKeyProvider;
> import java.io.IOException;
> import java.nio.file.Paths;
> public class TestSshd2 {
> public static void main(String[] args) throws IOException,
> InterruptedException {
> SecurityUtils.setAPrioriDisabledProvider("BC", true);
> SshServer sshd = SshServer.setUpDefaultServer();
> sshd.setPort(12133);
> sshd.setKeyPairProvider(new
> SimpleGeneratorHostKeyProvider(Paths.get("/tmp/aa.key")));
> sshd.setPasswordAuthenticator((username, password, session) -> true);
> sshd.setForwardingFilter(AcceptAllForwardingFilter.INSTANCE);
> sshd.start();
> Thread.sleep(100000000);
> }
> }
> {code}
> Step2. start ssh client and iperf3 server:
> {code:java}
> ssh -o 'ExitOnForwardFailure yes' -p 12133 -f -x -N -T -L
> 0.0.0.0:15678:127.0.0.1:12345 [email protected]
> iperf3 -s -p 12345
> {code}
> Step3. run iperf3 client:
> {code:java}
> iperf3 -c 127.0.0.1 -i 1 -t 120 -p 15678 -P 8 --reverse
> {code}
> *-R, --reverse run in reverse mode (server sends, client receives)*
> SSHD will receive a lot of data but will not be able to forward it in time.
> log when OOM:
> {code:java}
> 17:52:25.195 [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-1] WARN
> org.apache.sshd.common.io.nio2.Nio2Session -
> exceptionCaught(Nio2Session[local=/127.0.0.1:33524, remote=/127.0.0.1:12345])
> Exception handler threw OutOfMemoryError, closing the session: GC overhead
> limit exceeded17:52:25.195
> [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-1] WARN
> org.apache.sshd.common.io.nio2.Nio2Session -
> exceptionCaught(Nio2Session[local=/127.0.0.1:33524, remote=/127.0.0.1:12345])
> Exception handler threw OutOfMemoryError, closing the session: GC overhead
> limit exceeded at
> org.apache.sshd.common.io.nio2.Nio2CompletionHandler.completed(Nio2CompletionHandler.java:37)
> at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126) at
> sun.nio.ch.Invoker.invokeDirect(Invoker.java:157) at
> sun.nio.ch.UnixAsynchronousSocketChannelImpl.implWrite(UnixAsynchronousSocketChannelImpl.java:736)
> at
> sun.nio.ch.AsynchronousSocketChannelImpl.write(AsynchronousSocketChannelImpl.java:382)
> at
> sun.nio.ch.AsynchronousSocketChannelImpl.write(AsynchronousSocketChannelImpl.java:399)
> at
> org.apache.sshd.common.io.nio2.Nio2Session.doWriteCycle(Nio2Session.java:420)
> at
> org.apache.sshd.common.io.nio2.Nio2Session.startWriting(Nio2Session.java:404)
> at
> org.apache.sshd.common.io.nio2.Nio2Session.finishWrite(Nio2Session.java:495)
> at
> org.apache.sshd.common.io.nio2.Nio2Session.handleCompletedWriteCycle(Nio2Session.java:465)
> at
> org.apache.sshd.common.io.nio2.Nio2Session$2.onCompleted(Nio2Session.java:429)
> at
> org.apache.sshd.common.io.nio2.Nio2Session$2.onCompleted(Nio2Session.java:426)17:52:25.639
> [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-6] WARN
> org.apache.sshd.common.io.nio2.Nio2Session -
> exceptionCaught(Nio2Session[local=/127.0.0.1:33530, remote=/127.0.0.1:12345])
> Exception handler threw OutOfMemoryError, closing the session: GC overhead
> limit exceeded at
> org.apache.sshd.common.io.nio2.Nio2CompletionHandler.lambda$completed$0(Nio2CompletionHandler.java:38)
> at java.security.AccessController.doPrivileged(Native Method) at
> org.apache.sshd.common.io.nio2.Nio2CompletionHandler.completed(Nio2CompletionHandler.java:37)
> at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126) at
> sun.nio.ch.Invoker.invokeDirect(Invoker.java:157) at
> sun.nio.ch.UnixAsynchronousSocketChannelImpl.implWrite(UnixAsynchronousSocketChannelImpl.java:736)17:52:26.045
> [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-2] DEBUG
> org.apache.sshd.common.io.nio2.Nio2Session -
> exceptionCaught(Nio2Session[local=/127.0.0.1:33522, remote=/127.0.0.1:12345])
> caught OutOfMemoryError[GC overhead limit exceeded] - calling
> handler17:52:26.045 [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-2]
> DEBUG org.apache.sshd.server.forward.TcpipServerChannel -
> exceptionCaught(TcpipServerChannel[id=3,
> recipient=4]-ServerSessionImpl[test5@/127.0.0.1:53702]) signal close
> immediately=false due to OutOfMemoryError[GC overhead limit
> exceeded]17:52:26.045 [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-2]
> DEBUG org.apache.sshd.server.forward.TcpipServerChannel -
> close(TcpipServerChannel[id=3,
> recipient=4]-ServerSessionImpl[test5@/127.0.0.1:53702])[Graceful] state
> already Graceful17:52:26.794
> [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-3] WARN
> org.apache.sshd.common.io.nio2.Nio2Session -
> exceptionCaught(Nio2Session[local=/127.0.0.1:33528, remote=/127.0.0.1:12345])
> Exception handler threw OutOfMemoryError, closing the session: GC overhead
> limit exceeded at
> sun.nio.ch.AsynchronousSocketChannelImpl.write(AsynchronousSocketChannelImpl.java:382)
> at
> sun.nio.ch.AsynchronousSocketChannelImpl.write(AsynchronousSocketChannelImpl.java:399)
> at
> org.apache.sshd.common.io.nio2.Nio2Session.doWriteCycle(Nio2Session.java:420)
> at
> org.apache.sshd.common.io.nio2.Nio2Session.startWriting(Nio2Session.java:404)
> at
> org.apache.sshd.common.io.nio2.Nio2Session.finishWrite(Nio2Session.java:495)
> at
> org.apache.sshd.common.io.nio2.Nio2Session.handleCompletedWriteCycle(Nio2Session.java:465)
> at
> org.apache.sshd.common.io.nio2.Nio2Session$2.onCompleted(Nio2Session.java:429)
> at
> org.apache.sshd.common.io.nio2.Nio2Session$2.onCompleted(Nio2Session.java:426)
> at
> org.apache.sshd.common.io.nio2.Nio2CompletionHandler.lambda$completed$0(Nio2CompletionHandler.java:38)17:52:26.045
> [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-2] DEBUG
> org.apache.sshd.common.io.nio2.Nio2Session -
> close(Nio2Session[local=/127.0.0.1:33522, remote=/127.0.0.1:12345]) Closing
> immediately at java.security.AccessController.doPrivileged(Native
> Method)17:52:26.869 [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-2]
> DEBUG org.apache.sshd.common.io.nio2.Nio2Session -
> doCloseImmediately(Nio2Session[local=/127.0.0.1:33522,
> remote=/127.0.0.1:12345]) closing
> socket=sun.nio.ch.UnixAsynchronousSocketChannelImpl[connected
> local=/127.0.0.1:33522 remote=/127.0.0.1:12345] at
> org.apache.sshd.common.io.nio2.Nio2CompletionHandler.completed(Nio2CompletionHandler.java:37)
> at sun.nio.ch.Invoker.invokeUnchecked(Invoker.java:126) at
> sun.nio.ch.Invoker.invokeDirect(Invoker.java:157)17:52:27.568
> [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-6] DEBUG
> org.apache.sshd.common.io.nio2.Nio2Session -
> exceptionCaught(Nio2Session[local=/127.0.0.1:33530, remote=/127.0.0.1:12345])
> caught OutOfMemoryError[GC overhead limit exceeded] - calling
> handler17:52:27.568 [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-6]
> DEBUG org.apache.sshd.server.forward.TcpipServerChannel -
> exceptionCaught(TcpipServerChannel[id=7,
> recipient=8]-ServerSessionImpl[test5@/127.0.0.1:53702]) signal close
> immediately=false due to OutOfMemoryError[GC overhead limit
> exceeded]17:52:27.568 [sshd-SshServer[5bcea91b](port=12133)-nio2-thread-6]
> DEBUG org.apache.sshd.server.forward.TcpipServerChannel -
> close(TcpipServerChannel[id=7,
> recipient=8]-ServerSessionImpl[test5@/127.0.0.1:53702])[Graceful] state
> already Graceful at
> sun.nio.ch.UnixAsynchronousSocketChannelImpl.implWrite(UnixAsynchronousSocketChannelImpl.java:736)
> at
> sun.nio.ch.AsynchronousSocketChannelImpl.write(AsynchronousSocketChannelImpl.java:382)
> {code}
--
This message was sent by Atlassian Jira
(v8.3.4#803005)
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]