Skip to content

LineOutputHandler emits a spurious empty line when a CRLF line ending is split across two reads #85

Description

@matt-edmondson

What's wrong

LineOutputHandler.ProcessDataByLine (RunCommand/LineOutputHandler.cs:63-73) calls data.ReplaceLineEndings() on each incoming chunk before appending it to the buffer. ReplaceLineEndings treats a lone \r and a lone \n each as a full line break. So when a chunk ends in \r and the next chunk starts with \n, the one CRLF becomes two Environment.NewLines, and the handler raises an extra empty line.

Chunks are split wherever a 4096-char read ends (AsyncProcessStreamReader), or wherever the child's writes happen to fall. Output from any tool that writes CRLF (every native Windows tool, and many cross-platform ones on Windows) is therefore corrupted at random positions.

Failure scenario

Feed the handler "x\r" and then "\ny\n" (this is what happens when a read boundary lands between \r and \n):

line:[x]
line:[]
line:[y]

Expected output is x, y. A caller that counts lines or treats a blank line as a separator (for example, the record separator in git log output) gets wrong results. This happens intermittently, depending on where the reads split.

Suggested fix

Normalize line endings after concatenating onto the buffer, not per chunk. Also hold back a trailing \r in the buffer until the next chunk (or end of stream) shows whether a \n follows. For example: buffer += data;, then scan for \n or for a \r that is not the last character, split lines there, and strip a trailing \r from each line. Add a unit test next to HandleStandardOutputDataShouldBufferIncompleteLines that splits \r\n across two calls.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

bugSomething isn't working

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions