Skip to content

Update NamedPipeStreamReader to handle multiple sequential messages#341

Closed
jamill wants to merge 5 commits intomicrosoft:masterfrom
jamill:named_pipe_tweak
Closed

Update NamedPipeStreamReader to handle multiple sequential messages#341
jamill wants to merge 5 commits intomicrosoft:masterfrom
jamill:named_pipe_tweak

Conversation

@jamill
Copy link
Member

@jamill jamill commented Oct 4, 2018

Originally, the NamedPipeStreamReader assumed that only a single message would be sent over the pipe at a time. This allowed for some simplifications to the NamedPipeStreamReader. However, this assumption does not hold for and results in incorrect behavior when multiple messages are sent (see #333).

This series of commits adds test cases demonstrating this issue and updates the NamedPipeStreamReader to handle multiple sequential messages on the NamedPipe stream.

Fixes #333

jamill added 3 commits October 4, 2018 14:37
The NamedPipe protocol did not handle the case where multiple messages
were sent sequentially without waiting for a response from the other
side. This changes the NamedPipeStreamReader to inspect all the bytes
and handle cases where there are multiple messages sent.
Previously, the NamedPipeStreamReader made the assumption that only a
single message would be sent at a time. This assumption simplified its
logic, and it assumed that the end of the message would be at the end of
the buffer. If the buffer contained multiple messages, it might report
multiple messages as a single message.

This change updates the NamedPipeStreamReader to handle a message
terminated at any point.
// We have read all the bytes in the buffer -
// set the start of the next message to be
// the following index.
this.nextMessageChunkStartIndex = i;
Copy link
Member

@wilbaker wilbaker Oct 4, 2018

Choose a reason for hiding this comment

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

What if the message (or the processing of multiple messages) is long enough that we've filled up this.buffer? Does this.nextMessageChunkStartIndex need to get set back to 0?

(I'm not sure what the impact of this change would be on the other index related checks)

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes - nextMessageChunkStartIndex gets reset on the Read()

Copy link
Member

Choose a reason for hiding this comment

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

Ok thanks, I think I was getting messageChunkStartIndex and nextMessageChunkStartIndex confused when reading through the while loop.

Copy link
Contributor

@sanoursa sanoursa left a comment

Choose a reason for hiding this comment

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

This is currently very complex, and I worry that it will be difficult to maintain (or even to ensure it's bug-free now). Please take a look and see if we can simplify it down.

///
/// This format was chosen so that
/// 1) A reasonable range of values can be transmitted across the pipe,
/// including including null and bytes that represent newline characters,
Copy link
Contributor

Choose a reason for hiding this comment

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

Typo: "including including"

/// The number of bytes that have been read from the stream and into
/// the buffer.
/// </summary>
private int numBytesReadIntoBuffer;
Copy link
Contributor

Choose a reason for hiding this comment

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

This variable looks like it represents the number of bytes left to consume, but it actually just represents the number of bytes that we got back in the last read. I think this will be confusing to maintain, and it would be nice to eliminate this variable if we can. Still reading...

Copy link
Contributor

Choose a reason for hiding this comment

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

Yea I think we should either treat buffer as a circular buffer, and track a start index and number of unread bytes, or else just make the buffer big enough that it won't need to wrap and simplify this down. The logic is currently very hard to follow.

Copy link
Contributor

Choose a reason for hiding this comment

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

Or yet another option would be to get rid of buffer altogether, and only read one byte at a time until you find the message terminator. How much would that affect perf? If it's not a significant hit, that will eliminate most of the complexity here.

Copy link
Member Author

Choose a reason for hiding this comment

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

else just make the buffer big enough that it won't need to wrap and simplify this down

The message can contain user entered text (git commands) and arbitrary content (Modified Paths entries) - I don't think we can put a cap on the message buffer.

another option would be to get rid of buffer altogether,

I have not profiled it, but the msdn documentation includes a note about how inefficient this approach is Notes to Inheritors.

Copy link
Contributor

Choose a reason for hiding this comment

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

There's no question that reading one byte at a time will be slower, but how much will that impact our actual perf numbers on git commands?

If that doesn't pan out because the perf is bad, then let's chat about options for making this solution simpler.

}

[Test]
[Description("Verify that we can transmit message multiple messages in the same buffer")]
Copy link
Contributor

Choose a reason for hiding this comment

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

Please drop the description attributes. They tend to get stale, and the method name should just be the description anyway.

{
string chunkedMessage = new string('T', BufferSize + (BufferSize / 2));

// Verify that we corrently handle messages
Copy link
Member

Choose a reason for hiding this comment

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

nit: corrently

@sanoursa
Copy link
Contributor

sanoursa commented Oct 5, 2018

This was handled in #343

@sanoursa sanoursa closed this Oct 5, 2018
@jamill jamill deleted the named_pipe_tweak branch April 3, 2019 02:34
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.

4 participants