@@ -272,10 +272,11 @@ public async Task WorkerProcess_WaitForExit_NotStarted_Throws()
272
272
public async Task WorkerProcess_WaitForExit_Success_TaskCompletes ( )
273
273
{
274
274
// arrange
275
- using Process process = GetProcess ( exitCode : 0 ) ;
276
- _hostProcessMonitorMock . Setup ( m => m . RegisterChildProcess ( process ) ) ;
277
- _hostProcessMonitorMock . Setup ( m => m . UnregisterChildProcess ( process ) ) ;
278
- _workerProcessFactory . Setup ( m => m . CreateWorkerProcess ( It . IsNotNull < WorkerContext > ( ) ) ) . Returns ( process ) ;
275
+ await using ProcessWrapper wrapper = new ( exitCode : 0 ) ;
276
+ _hostProcessMonitorMock . Setup ( m => m . RegisterChildProcess ( wrapper . Process ) ) ;
277
+ _hostProcessMonitorMock . Setup ( m => m . UnregisterChildProcess ( wrapper . Process ) ) ;
278
+ _workerProcessFactory . Setup ( m => m . CreateWorkerProcess ( It . IsNotNull < WorkerContext > ( ) ) )
279
+ . Returns ( wrapper . Process ) ;
279
280
using var rpcWorkerProcess = GetRpcWorkerConfigProcess (
280
281
TestHelpers . GetTestWorkerConfigsWithExecutableWorkingDirectory ( ) . ElementAt ( 0 ) ) ;
281
282
@@ -290,10 +291,11 @@ public async Task WorkerProcess_WaitForExit_Success_TaskCompletes()
290
291
public async Task WorkerProcess_WaitForExit_Error_Rethrows ( )
291
292
{
292
293
// arrange
293
- using Process process = GetProcess ( exitCode : - 1 ) ;
294
- _hostProcessMonitorMock . Setup ( m => m . RegisterChildProcess ( process ) ) ;
295
- _hostProcessMonitorMock . Setup ( m => m . UnregisterChildProcess ( process ) ) ;
296
- _workerProcessFactory . Setup ( m => m . CreateWorkerProcess ( It . IsNotNull < WorkerContext > ( ) ) ) . Returns ( process ) ;
294
+ await using ProcessWrapper wrapper = new ( exitCode : - 1 ) ;
295
+ _hostProcessMonitorMock . Setup ( m => m . RegisterChildProcess ( wrapper . Process ) ) ;
296
+ _hostProcessMonitorMock . Setup ( m => m . UnregisterChildProcess ( wrapper . Process ) ) ;
297
+ _workerProcessFactory . Setup ( m => m . CreateWorkerProcess ( It . IsNotNull < WorkerContext > ( ) ) )
298
+ . Returns ( wrapper . Process ) ;
297
299
using var rpcWorkerProcess = GetRpcWorkerConfigProcess (
298
300
TestHelpers . GetTestWorkerConfigsWithExecutableWorkingDirectory ( ) . ElementAt ( 0 ) ) ;
299
301
@@ -310,13 +312,33 @@ private static Process GetProcess(int exitCode)
310
312
{
311
313
StartInfo = new ( )
312
314
{
313
- WindowStyle = ProcessWindowStyle . Hidden ,
314
315
FileName = OperatingSystem . IsWindows ( ) ? "cmd" : "bash" ,
315
316
Arguments = OperatingSystem . IsWindows ( ) ? $ "/C exit { exitCode } " : $ "-c \" exit { exitCode } \" ",
316
317
RedirectStandardError = true ,
317
318
RedirectStandardOutput = true ,
319
+ CreateNoWindow = true ,
320
+ ErrorDialog = false ,
321
+ UseShellExecute = false
318
322
}
319
323
} ;
320
324
}
325
+
326
+ private class ProcessWrapper ( int exitCode ) : IAsyncDisposable
327
+ {
328
+ public Process Process { get ; } = GetProcess ( exitCode ) ;
329
+
330
+ public async ValueTask DisposeAsync ( )
331
+ {
332
+ if ( ! Process . HasExited )
333
+ {
334
+ // We need to kill the entire process tree to ensure
335
+ // CI tests don't hang due to child processes lingering around.
336
+ Process . Kill ( entireProcessTree : true ) ;
337
+ await Process . WaitForExitAsync ( ) ;
338
+ }
339
+
340
+ Process . Dispose ( ) ;
341
+ }
342
+ }
321
343
}
322
344
}
0 commit comments