Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

The context in the writeBuffer function of NettyIoSession is throwing a null pointer exception. #587

Closed
wumengchao opened this issue Aug 28, 2024 · 12 comments
Assignees
Labels
bug An issue describing a bug in the code
Milestone

Comments

@wumengchao
Copy link

Version

2.13.2

Bug description

Triggering the port after a successful access forwarding.

Actual behavior

The R connection is directly disconnected.

Expected behavior

I hope to fix this issue.

Relevant log output

No response

Other information

No response

@tomaswolf
Copy link
Member

Sorry, this is not actionable. The description is too vague. Provide full stack traces (as text, not screenshots!), and explain how to reproduce the problem.

I can only guess that it might be some write on an already closed channel.

@wumengchao
Copy link
Author

exceptionCaught(ServerSessionImpl[deploy@/xx.xx.xx.xx:38684])[state=Opened] NullPointerException: Cannot invoke "io.netty.channel.ChannelHandlerContext.newPromise()" because "this.context" is null

@tomaswolf
Copy link
Member

Provide the full server log. I need to see what happened before that. Ideally you'd also have a backtrace for this exception. Maybe run your server with debug logging.

What exactly was the client doing?

@wumengchao
Copy link
Author

The client initiates createPortForwardingR using jsch, and then another jsch accesses the R channel through createPortForwardingL, which triggers this null problem.

@wumengchao
Copy link
Author

Additionally, there are some error logs like this:
SSH2_DISCONNECT_PROTOCOL_ERROR - Detected AuthTimeout after 120055/120000 ms.

@tomaswolf
Copy link
Member

Please provide full Java code to reproduce this problem.

@wumengchao
Copy link
Author

The process is quite complex, so I'll describe it in words. Let's assume: Client IP: 10.0.0.1, Server IP: 192.168.0.1. The client establishes a local port mapping from port 22 to remote port 1111 using jsch. By accessing 127.0.0.1:1111 from the server (192.168.0.1), we can access the client's SSH. Then, on the server, we use jsch to create a local port mapping from server port 2222 to the client's port 3333. Accessing 127.0.0.1:2222 on the server would reach port 3333 on the client, at which point an exception will be reported.

@tomaswolf
Copy link
Member

What is listening on 10.0.0.1:3333? And given that the server seems to be an Apache MINA sshd server, why is JSch being used to create this second tunnel? I also don't see what the first remote forward has to do with this failure in the second tunnel. The two tunnels seem to be unrelated.

It should be possible to mock your setup all on one machine and package it as some Java code.

I need to be able to reproduce the problem; otherwise any changes we might make would be shots in the dark.

We could just code around this NullPointerException, but without knowing why exactly it occurs in the first place and no regression tests we won't really have solved anything. The interesting question here is "why is the context null?". Probably the answer is "because the channel is already closed", and then the next interesting question is "why is the channel closed?". Once we know that, we can decide how to fix this. If the channel is rightly closed, then just coding around the NullPointerException might be a valid solution. If the channel should not be closed at all, then there is some other problem that needs to fixed.

To answer these questions I need to have a reproducible case.

@wumengchao
Copy link
Author

jsch is a method used on another system and cannot be changed. It just uses mina-sshd's SSH tunnel to complete tasks.

@wumengchao
Copy link
Author

wumengchao commented Aug 31, 2024

Only forwarding the SSH protocol port and sending a non-SSH protocol request (such as HTTP) will result in an error.

@wumengchao
Copy link
Author

wumengchao commented Aug 31, 2024

The following check has been added to the writeBuffer of NettyIoSession, and it is currently functioning normally:

if (context == null) {
return msg;
}
However, an exception still occurs:
SocketException: Connection reset
java.net.SocketException: Connection reset
at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:403)
at java.base/sun.nio.ch.SocketChannelImpl.implRead(SocketChannelImpl.java:435)
at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:493)
at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:255)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:356)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:788)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:724)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:650)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:562)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:994)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:1570)

@tomaswolf
Copy link
Member

However, an exception still occurs:

I'm not surprised. I do not understand what exactly you are doing, but the whole description so far sounds like some setup bug. Maybe you're not connecting ports the way you actually intended, and end up writing the wrong stuff to the wrong port.

Without seeing full code that reproduces the problem there is no way we could help.

BTW, the "fix"

if (context == null) {
  return msg;
}

is not correct; the msg future will never be fulfilled.

@tomaswolf tomaswolf self-assigned this Sep 7, 2024
@tomaswolf tomaswolf added the bug An issue describing a bug in the code label Sep 7, 2024
@tomaswolf tomaswolf added this to the 2.14.0 milestone Sep 7, 2024
tomaswolf added a commit that referenced this issue Sep 7, 2024
If a write occurs on an already closed channel, an NPE might occur.
Handle this case by setting a ChannelClosedException on the returned
future.

This prevents the NPE, but other code may still issue other exceptions
if a write on a closed channel occurs.

Bug: #587
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug An issue describing a bug in the code
Projects
None yet
Development

No branches or pull requests

2 participants