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

Heartbeat does not respond to timeout while waiting for a response from the server #268

Closed
IstominP opened this issue Nov 10, 2022 · 4 comments · Fixed by #274
Closed

Heartbeat does not respond to timeout while waiting for a response from the server #268

IstominP opened this issue Nov 10, 2022 · 4 comments · Fixed by #274
Assignees
Labels
bug An issue describing a bug in the code
Milestone

Comments

@IstominP
Copy link

IstominP commented Nov 10, 2022

If heartbeat is waiting for a response from the server and the response did not come within the allotted time, then we must kill the session because the server is not responding, in which case the lack of response to waiting for a response in org.apache.sshd.client.session.ClientConnectionService#sendHeartBeat looks like wrong behavior.

Should we do something like
if (!replyReceived.await(toWait, TimeUnit.MILLISECONDS)) { throw new TimeoutException("No response from server"); }
when waiting response on heartbeat request

timeout

Am I understanding heartbeat logic correctly?

@tomaswolf
Copy link
Member

Looks like you've found a bug. Indeed we neglect to deal with the return value of the await() call. On second thought, I have the impression this change in this class should just be rolled back. It has no benefit at all.

@tomaswolf tomaswolf added the bug An issue describing a bug in the code label Nov 10, 2022
@Brikman
Copy link

Brikman commented Nov 11, 2022

@tomaswolf can you explain in more detail please?

Did I understand correctly that you are proposing to roll back and generally refuse to wait for a response to a heartbeat?

Are there any disadvantages or fundamental errors in the solution proposed by @robober? Is it correct in principle to wait response to every heartbeat?

@tomaswolf
Copy link
Member

proposing to roll back

Yes.

and generally refuse to wait for a response to a heartbeat?

No. Seems to me that rolling back would use the synchronous session.request() method (again), which does wait for the response and which does throw a SocketTimeoutException if a timeout occurs. If that is correct, then rolling back would be the preferred solution since it simplifies the code quite a bit.

Are there any disadvantages or fundamental errors in the solution proposed by @robober?

No. But looking back at this code, I don't see anymore why I even changed it. Using the asynchronous global request but then waiting on the latch is still blocking of course. But heartbeats are sent from separate threads anyway, so this doesn't block an I/O thread.

@Brikman
Copy link

Brikman commented Nov 11, 2022

Thank you for explanation.

In this case, we will use our modified heartbeat for a while, waiting for fix in library.

@tomaswolf tomaswolf self-assigned this Nov 22, 2022
tomaswolf added a commit to tomaswolf/mina-sshd that referenced this issue Nov 22, 2022
If a reply is requested, but none arrives within the timeout, throw an
exception and terminate the connection.

This rolls back the changes made in ClientConnectionService in commit
de2f8fe. It's quite all right to use the synchronous implementation of
Session.request() because heartbeats are not sent from I/O threads.

Bug: apache#268
@tomaswolf tomaswolf added this to the 2.9.3 milestone Nov 22, 2022
tomaswolf added a commit to tomaswolf/mina-sshd that referenced this issue Nov 23, 2022
If a reply is requested, but none arrives within the timeout, throw an
exception and terminate the connection.

This rolls back the changes made in ClientConnectionService in commit
de2f8fe. It's quite all right to use the synchronous implementation of
Session.request() because heartbeats are not sent from I/O threads.

However, commit de2f8fe broke the contract specified in interface
Session, which says Session.request() must return "the buffer if the
request was successful, {@code null} otherwise." The implementation
from commit de2f8fe threw an exception instead.

This was wrong, and is corrected now in this commit. Note that this
means that a caller cannot distinguish between the server replying
SSH_MSG_UNIMPLEMENTED or SSH_MSG_REQUEST_FAILURE.

Where such distinction is needed, use an asynchronous global request
instead.

Bug: apache#268
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

Successfully merging a pull request may close this issue.

3 participants