@@ -151,7 +151,17 @@ public async Task<ITransport> ConnectAsync(CancellationToken cancellationToken =
151151 stderrRollingLog . Enqueue ( data ) ;
152152 }
153153
154- _options . StandardErrorLines ? . Invoke ( data ) ;
154+ try
155+ {
156+ _options . StandardErrorLines ? . Invoke ( data ) ;
157+ }
158+ catch ( Exception ex )
159+ {
160+ // Prevent exceptions in the user callback from propagating
161+ // to the background thread that dispatches ErrorDataReceived,
162+ // which would crash the process.
163+ LogStderrCallbackFailed ( logger , endpointName , ex ) ;
164+ }
155165
156166 LogReadStderr ( logger , endpointName , data ) ;
157167 }
@@ -230,12 +240,10 @@ internal static void DisposeProcess(
230240
231241 // Ensure all redirected stderr/stdout events have been dispatched
232242 // before disposing. Only the no-arg WaitForExit() guarantees this;
233- // WaitForExit(int) (as used by KillTree) does not.
234- // This should not hang: either the process already exited on its own
235- // (no child processes holding handles), or KillTree killed the entire
236- // process tree. If it does take too long, the test infrastructure's
237- // own timeout will catch it.
238- if ( ! processRunning && HasExited ( process ) )
243+ // WaitForExit(int) (as used by KillTree) does not. We must call
244+ // this whether the process exited on its own or was killed above,
245+ // otherwise ErrorDataReceived handlers may fire after Dispose().
246+ if ( HasExited ( process ) )
239247 {
240248 process . WaitForExit ( ) ;
241249 }
@@ -299,6 +307,9 @@ private static string EscapeArgumentString(string argument) =>
299307 [ LoggerMessage ( Level = LogLevel . Information , Message = "{EndpointName} received stderr log: '{Data}'." ) ]
300308 private static partial void LogReadStderr ( ILogger logger , string endpointName , string data ) ;
301309
310+ [ LoggerMessage ( Level = LogLevel . Warning , Message = "{EndpointName} StandardErrorLines callback failed." ) ]
311+ private static partial void LogStderrCallbackFailed ( ILogger logger , string endpointName , Exception exception ) ;
312+
302313 [ LoggerMessage ( Level = LogLevel . Information , Message = "{EndpointName} started server process with PID {ProcessId}." ) ]
303314 private static partial void LogTransportProcessStarted ( ILogger logger , string endpointName , int processId ) ;
304315
0 commit comments