@@ -16,7 +16,7 @@ namespace VirtualClient.Common
1616 /// </summary>
1717 public static class ProcessExtensions
1818 {
19- /// <summary>
19+ /// <summary>
2020 /// Sets the process for interactive mode (e.g. standard output and input redirected).
2121 /// </summary>
2222 /// <param name="process">Represents a process on the system.</param>
@@ -37,69 +37,13 @@ public static IProcessProxy Interactive(this IProcessProxy process)
3737 /// An absolute timeout to apply for the case that the process does not finish in the amount of time expected. If the
3838 /// timeout is reached a <see cref="TimeoutException"/> exception will be thrown.
3939 /// </param>
40- /// <param name="withExitConfirmation">True to confirm an exit code before returning. Default = false.</param>
41- public static async Task StartAndWaitAsync ( this IProcessProxy process , CancellationToken cancellationToken , TimeSpan ? timeout = null , bool withExitConfirmation = false )
40+ public static async Task StartAndWaitAsync ( this IProcessProxy process , CancellationToken cancellationToken , TimeSpan ? timeout = null )
4241 {
4342 process . ThrowIfNull ( nameof ( process ) ) ;
4443
4544 if ( process . Start ( ) )
4645 {
4746 await process . WaitForExitAsync ( cancellationToken , timeout ) ;
48-
49- if ( withExitConfirmation )
50- {
51- // There is a race condition-style flaw in the .NET implementation of the
52- // WaitForExit() method. The race condition allows for the process to exit after
53- // completion but for a period of time to pass before the kernel completes all finalization
54- // and cleanup steps (e.g. setting an exit code). To help prevent downstream issues that
55- // happen when attempting to access properties on the process during this race condition period
56- // of time, we are adding in an extra check on the process HasExited.
57- //
58- // Example of error hit during race condition period of time:
59- // Process must exit before requested information can be determined.
60- DateTime exitTime = DateTime . UtcNow . AddMinutes ( 2 ) ;
61- int exitCode = - 1 ;
62- bool confirmed = false ;
63-
64- while ( DateTime . UtcNow < exitTime )
65- {
66- try
67- {
68- // If the exit code is not available, this line will throw an exception.
69- exitCode = process . ExitCode ;
70- confirmed = true ;
71- break ;
72- }
73- catch
74- {
75- // Wait, but don't throttle the CPU.
76- await Task . Delay ( 1000 ) ;
77- }
78- }
79-
80- if ( ! confirmed )
81- {
82- try
83- {
84- string processName = null ;
85- ProcessExtensions . TryGetValue < string > (
86- ( ) =>
87- {
88- return $ "{ Path . GetFileName ( process ? . StartInfo . FileName ) } { process ? . StartInfo . Arguments } "? . Trim ( ) ;
89- } ,
90- out processName ) ;
91-
92- int processId = - 1 ;
93- ProcessExtensions . TryGetValue < int > ( ( ) => process . Id , out processId ) ;
94-
95- Console . Error . WriteLine ( $ "Process exit confirmation failed for process '{ processName } (id={ processId } )'.") ;
96- }
97- catch
98- {
99- // Do not allow any exceptions to surface from here.
100- }
101- }
102- }
10347 }
10448 }
10549
0 commit comments