@@ -311,9 +311,9 @@ internal enum ReadMode
311311
312312 internal bool EofSent => _channel . EofSent ;
313313
314- private void WriteEof ( bool noThrow )
314+ private void WriteEof ( bool noThrow , bool forStream = false )
315315 {
316- _channel . WriteEof ( noThrow ) ;
316+ _channel . WriteEof ( noThrow , forStream ) ;
317317 }
318318
319319 /// <summary>
@@ -355,9 +355,12 @@ public bool SendSignal(string signalName)
355355 /// <param name="buffer">The buffer to write.</param>
356356 /// <param name="cancellationToken">Token to cancel the operation.</param>
357357 public ValueTask WriteAsync ( ReadOnlyMemory < byte > buffer , CancellationToken cancellationToken = default )
358+ => WriteAsync ( buffer , cancellationToken , forStream : false ) ;
359+
360+ internal ValueTask WriteAsync ( ReadOnlyMemory < byte > buffer , CancellationToken cancellationToken , bool forStream )
358361 {
359362 ThrowIfDisposed ( ) ;
360- return _channel . WriteAsync ( buffer , cancellationToken ) ;
363+ return _channel . WriteAsync ( buffer , cancellationToken , forStream ) ;
361364 }
362365
363366 /// <summary>
@@ -510,9 +513,11 @@ public StreamReader ReadAsStreamReader(StderrHandler stderrHandler, int bufferSi
510513 {
511514 CheckReadMode ( readMode ) ;
512515
516+ bool forStream = readMode == ReadMode . ReadStream ;
517+
513518 while ( true )
514519 {
515- ( ChannelReadType ReadType , int BytesRead ) = await _channel . ReadAsync ( stdoutBuffer , stderrBuffer , cancellationToken ) . ConfigureAwait ( false ) ; ;
520+ ( ChannelReadType ReadType , int BytesRead ) = await _channel . ReadAsync ( stdoutBuffer , stderrBuffer , cancellationToken , forStream ) . ConfigureAwait ( false ) ; ;
516521 switch ( ReadType )
517522 {
518523 case ChannelReadType . StandardOutput :
@@ -993,42 +998,31 @@ public override async ValueTask<int> ReadAsync(Memory<byte> buffer, Cancellation
993998 return 0 ;
994999 }
9951000
996- try
1001+ while ( true )
9971002 {
998- while ( true )
999- {
1000- Memory < byte > ? stderrBuffer = _stderrBuffer != null ? ( Memory < byte > ? ) _stderrBuffer : default ( Memory < byte > ? ) ;
1001- ( bool isError , int bytesRead ) = await _process . ReadAsync ( ReadMode . ReadStream , buffer , stderrBuffer , cancellationToken ) . ConfigureAwait ( false ) ;
1003+ Memory < byte > ? stderrBuffer = _stderrBuffer != null ? ( Memory < byte > ? ) _stderrBuffer : default ( Memory < byte > ? ) ;
1004+ ( bool isError , int bytesRead ) = await _process . ReadAsync ( ReadMode . ReadStream , buffer , stderrBuffer , cancellationToken ) . ConfigureAwait ( false ) ;
10021005
1003- if ( isError )
1006+ if ( isError )
1007+ {
1008+ // Handle stderr data
1009+ if ( _stderrHandler != null && bytesRead > 0 )
10041010 {
1005- // Handle stderr data
1006- if ( _stderrHandler != null && bytesRead > 0 )
1007- {
1008- await _stderrHandler . HandleBufferAsync ( _stderrBuffer . AsMemory ( 0 , bytesRead ) , cancellationToken ) . ConfigureAwait ( false ) ;
1009- }
1010- // Continue reading to get stdout data
1011- continue ;
1011+ await _stderrHandler . HandleBufferAsync ( _stderrBuffer . AsMemory ( 0 , bytesRead ) , cancellationToken ) . ConfigureAwait ( false ) ;
10121012 }
1013- else
1013+ // Continue reading to get stdout data
1014+ continue ;
1015+ }
1016+ else
1017+ {
1018+ // Signal end of stream to the stderr handler.
1019+ if ( _stderrHandler != null && bytesRead == 0 )
10141020 {
1015- // Signal end of stream to the stderr handler.
1016- if ( _stderrHandler != null && bytesRead == 0 )
1017- {
1018- await _stderrHandler . HandleBufferAsync ( default , cancellationToken ) . ConfigureAwait ( false ) ;
1019- }
1020- return bytesRead ;
1021+ await _stderrHandler . HandleBufferAsync ( default , cancellationToken ) . ConfigureAwait ( false ) ;
10211022 }
1023+ return bytesRead ;
10221024 }
10231025 }
1024- catch ( OperationCanceledException )
1025- {
1026- throw ;
1027- }
1028- catch ( Exception ex )
1029- {
1030- throw new IOException ( $ "Failed to read from remote process: { ex . Message } ", ex ) ;
1031- }
10321026 }
10331027
10341028 public override async Task < int > ReadAsync ( byte [ ] buffer , int offset , int count , CancellationToken cancellationToken )
@@ -1103,27 +1097,14 @@ public override Task FlushAsync(CancellationToken cancellationToken = default)
11031097 return Task . CompletedTask ; // WriteAsync always flushes.
11041098 }
11051099
1106- public async override ValueTask WriteAsync ( System . ReadOnlyMemory < byte > buffer , CancellationToken cancellationToken = default ( CancellationToken ) )
1107- {
1108- try
1109- {
1110- await _process . WriteAsync ( buffer , cancellationToken ) . ConfigureAwait ( false ) ;
1111- }
1112- catch ( OperationCanceledException )
1113- {
1114- throw ;
1115- }
1116- catch ( Exception ex )
1117- {
1118- throw new IOException ( $ "Failed to write to remote process: { ex . Message } ", ex ) ;
1119- }
1120- }
1100+ public override ValueTask WriteAsync ( System . ReadOnlyMemory < byte > buffer , CancellationToken cancellationToken = default ( CancellationToken ) )
1101+ => _process . WriteAsync ( buffer , cancellationToken , forStream : true ) ;
11211102
11221103 public override void Close ( )
11231104 {
11241105 // The base Stream class calls Close for implementing Dispose.
11251106 // We mustn't throw to avoid throwing on Dispose.
1126- _process . WriteEof ( noThrow : true ) ;
1107+ _process . WriteEof ( noThrow : true , forStream : true ) ;
11271108 }
11281109 }
11291110}
0 commit comments