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

Fixes for ShellStream.Expect, ShellStream.Read, ShellStream.Write, and NullReferenceExceptions. #458

Closed
wants to merge 5 commits into from

Conversation

keithallenjackson
Copy link

@keithallenjackson keithallenjackson commented Aug 12, 2018

Adds tests (reproducing the issues) and code fixes for issues #454, #453, #432, #424, #180, #444, #301, #302.

@keithallenjackson keithallenjackson changed the title Fixes Fix for ShellStream.Expect(Regex, TimeSpan) returning string past the matched buffer. Aug 12, 2018
+ ShellStream.Expect no longer throws NullReferenceException when channel unexpectedly disconnects.
+ Adds Disconnect event to ShellStream.
+ Adds Disposed property to ShellStream to read internal disposed state.
@keithallenjackson keithallenjackson changed the title Fix for ShellStream.Expect(Regex, TimeSpan) returning string past the matched buffer. Fixes for ShellStream.Expect and NullReferenceExceptions. Aug 18, 2018
@VAllens
Copy link

VAllens commented Aug 18, 2018

This is great, thank you.

@keithallenjackson keithallenjackson changed the title Fixes for ShellStream.Expect and NullReferenceExceptions. Fixes for ShellStream.Expect, ShellStream.Read, ShelStream.Write, and NullReferenceExceptions. Aug 30, 2018
@keithallenjackson keithallenjackson changed the title Fixes for ShellStream.Expect, ShellStream.Read, ShelStream.Write, and NullReferenceExceptions. Fixes for ShellStream.Expect, ShellStream.Read, ShellStream.Write, and NullReferenceExceptions. Aug 30, 2018
src/Renci.SshNet/ShellStream.cs Outdated Show resolved Hide resolved
/// <summary>
/// Whether the instance is disposed.
/// </summary>
public bool Disposed
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not expose this.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While I'm not a fan of exposing the "Disposed" state of an object (the User API should have complete control of that), this was added to check for a disposed state since an unexpected channel closure could cause the ShellStream to Dispose without explicit user API calls. Should I change the event handler for _channel disconect to not Dispose the ShellStream? Essentially, an abrupt channel closure puts the ShellStream in a 'half-used'/'half-disposed' state. Let me know your thoughts.

src/Renci.SshNet/ShellStream.cs Outdated Show resolved Hide resolved
src/Renci.SshNet/ShellStream.cs Outdated Show resolved Hide resolved
@@ -550,6 +575,9 @@ public string Expect(Regex regex, TimeSpan timeout)
{
var text = string.Empty;

// Flush the write buffer in case expecting output from previous write.
if (!_isDisposed) Flush();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not something to change as part of this PR, but shouldn't we throw an ObjectDisposedException here (and consider the same for a few other methods) when the channel is closed or the ShellStream is disposed?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This goes back to the "half-used"/"half-Disposed" issue when an abrupt channel closure causes the ShellStream to abruptly be in a Disposed state without explicit user interaction. Under normal API usage, I agree 100% - Disposed state should be private, calling methods on a Disposed object should throw an ObjectDisposedException, and all of this behavior is appropriate because it is up to the user to set the 'disposed' state alone. Essentially, the user caused the Disposal, so therefore should know better than to use an object he/she disposed.

In this object, that behavior is not present. Maybe I should make a new private variable that specifies if the ShellStream is in a 'half-open' state? If so, how should the Write methods behave under this state? I'm genuinely curious about your thoughts. Thanks!

src/Renci.SshNet/ShellStream.cs Outdated Show resolved Hide resolved
src/Renci.SshNet/ShellStream.cs Outdated Show resolved Hide resolved
Copy link
Author

@keithallenjackson keithallenjackson left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All that's left to discuss is the behavior of Dispose and abrupt channel closure.

@keithallenjackson
Copy link
Author

How about this:

States

  • Normal, in use: Performs normal operations with standard Timeouts (as already written)
  • Channel Closed, Not Disposed: Throws either an SshConnectionException or ChannelClosedException when attempting to use Read, Write, or Expect
  • Disposed: Throws ObjectDisposedException

Additions

  • Closed Event: Only occurs when the Channel closes and the instance is NOT Disposed/Disposing
  • Closed EventArgs: Has properties containing the remaining input and output buffers. That way if/when an abrupt channel closure occurs, the User may see what was not sent and any remaining data within the input.

@drieseng
Copy link
Member

drieseng commented Sep 3, 2018

Quick and incomplete feedback:

  • We should not dispose the ShellStream when the channel is closed.
  • When disposed, we should throw an ObjectDisposedException in all methods (except for Dispose() of course).
  • When the channel is closed, we should throw an exception in the Write methods. The Read and Expect methods should return / operate on buffered data, and only throw an exception when the channel is closed and the buffer is empty at the time of the invocation.

lipmas added a commit to bastionzero/SSH.NET that referenced this pull request Oct 29, 2020
@keithallenjackson
Copy link
Author

Got busy with work and completely forgot about this. This is so out of date, there is no reason to keep it around. I'm closing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants