Skip to content

Commit 71b8ecc

Browse files
committed
Modify the default timeouts for process SafeKill. Change defaults for InMemoryProcess construction for fast exits.
1 parent 0acd25d commit 71b8ecc

4 files changed

Lines changed: 28 additions & 54 deletions

File tree

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.1.22
1+
2.1.23

src/VirtualClient/VirtualClient.Common/ProcessExtensions.cs

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -139,20 +139,5 @@ public static Task<IProcessProxy> WaitForResponseAsync(
139139

140140
return process.WaitForResponseAsync(new Regex(response, comparisonOptions), cancellationToken, timeout);
141141
}
142-
143-
private static T SafeGet<T>(Func<T> propertyAccessor)
144-
where T : IConvertible
145-
{
146-
T propertyValue = default(T);
147-
try
148-
{
149-
propertyValue = propertyAccessor.Invoke();
150-
}
151-
catch
152-
{
153-
}
154-
155-
return propertyValue;
156-
}
157142
}
158143
}

src/VirtualClient/VirtualClient.Core/ProcessExtensions.cs

Lines changed: 24 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -93,50 +93,36 @@ public static bool IsErrored(this IProcessProxy process, IEnumerable<int> succes
9393
/// </summary>
9494
/// <param name="process">The process to kill.</param>
9595
/// <param name="logger">The logger to use to write trace information.</param>
96-
/// <param name="timeout">Max duration to wait for exit, default to 3 minutes.</param>
97-
public static void SafeKill(this IProcessProxy process, ILogger logger = null, TimeSpan timeout = default)
96+
/// <param name="confirmationWaitTime">Max duration to wait for exit. Default = 10 seconds. Use TimeSpan.Zero for no wait.</param>
97+
public static void SafeKill(this IProcessProxy process, ILogger logger = null, TimeSpan? confirmationWaitTime = null)
9898
{
99-
TimeSpan effectiveTimeout = timeout == default ? TimeSpan.FromMinutes(3) : timeout;
100-
DateTime exitTime = DateTime.UtcNow.Add(effectiveTimeout);
101-
List<Exception> errors = new List<Exception>();
99+
TimeSpan effectiveTimeout = confirmationWaitTime ?? TimeSpan.FromSeconds(10);
102100

103-
using (CancellationTokenSource tokenSource = new CancellationTokenSource(effectiveTimeout))
101+
if (!process.HasExited)
104102
{
105-
while (DateTime.UtcNow < exitTime)
103+
// Process confirmed exited
104+
try
106105
{
107-
if (process.HasExited)
108-
{
109-
// Process confirmed exited
110-
break;
111-
}
106+
process.Kill(true);
112107

113-
try
114-
{
115-
process.Kill(true);
116-
process.WaitForExitAsync(tokenSource.Token).GetAwaiter().GetResult();
117-
}
118-
catch (Exception exc)
108+
if (confirmationWaitTime != TimeSpan.Zero)
119109
{
120-
errors.Add(exc);
110+
process.WaitForExitAsync(CancellationToken.None, confirmationWaitTime).GetAwaiter().GetResult();
121111
}
122112
}
123-
}
124-
125-
if (!process.HasExited)
126-
{
127-
string processName = SafeGet<string>(() => process.Name);
128-
int processId = SafeGet<int>(() => process.Id);
129-
130-
EventContext errorContext = EventContext.Persisted();
131-
errorContext.AddProcessDetails(process.ToProcessDetails(process.Name));
132-
if (errors.Any())
113+
catch (Exception exc)
133114
{
134-
errorContext.AddError(new AggregateException(
115+
string processName = SafeGet<string>(() => process.Name);
116+
int processId = SafeGet<int>(() => process.Id);
117+
118+
EventContext errorContext = EventContext.Persisted();
119+
errorContext.AddProcessDetails(process.ToProcessDetails(process.Name));
120+
errorContext.AddError(new WorkloadException(
135121
$"Process kill attempt failed (id={processId}, name={processName}, timeout={effectiveTimeout}).",
136-
errors));
137-
}
122+
exc));
138123

139-
logger?.LogMessage($"ProcessKillFailed.{processName}", LogLevel.Warning, errorContext);
124+
logger?.LogMessage($"ProcessKillFailed.{processName}", LogLevel.Warning, errorContext);
125+
}
140126
}
141127
}
142128

@@ -181,11 +167,11 @@ public static void SafeKill(this ProcessManager processManager, IEnumerable<stri
181167
/// </summary>
182168
/// <param name="processManager">Provides functionality for creating processes.</param>
183169
/// <param name="process">The process to kill.</param>
184-
/// <param name="timeout">Max duration to wait for exit, default to 3 minutes.</param>
185170
/// <param name="logger">The logger to use to write trace information.</param>
186-
public static void SafeKill(this ProcessManager processManager, IProcessProxy process, ILogger logger = null, TimeSpan timeout = default)
171+
/// <param name="confirmationWaitTime">Max duration to wait for exit. Default = 10 seconds. Use TimeSpan.Zero for no wait.</param>
172+
public static void SafeKill(this ProcessManager processManager, IProcessProxy process, ILogger logger = null, TimeSpan? confirmationWaitTime = null)
187173
{
188-
TimeSpan effectiveTimeout = timeout == default ? TimeSpan.FromMinutes(3) : timeout;
174+
TimeSpan effectiveTimeout = confirmationWaitTime ?? TimeSpan.FromSeconds(10);
189175

190176
using (CancellationTokenSource tokenSource = new CancellationTokenSource(effectiveTimeout))
191177
{
@@ -201,7 +187,7 @@ public static void SafeKill(this ProcessManager processManager, IProcessProxy pr
201187
{
202188
using (IProcessProxy kill = processManager.CreateProcess("kill", $"-9 {processId}"))
203189
{
204-
kill.StartAndWaitAsync(tokenSource.Token, timeout)
190+
kill.StartAndWaitAsync(tokenSource.Token, confirmationWaitTime)
205191
.GetAwaiter().GetResult();
206192

207193
// 0 = Success
@@ -219,7 +205,7 @@ public static void SafeKill(this ProcessManager processManager, IProcessProxy pr
219205
{
220206
using (IProcessProxy taskkill = processManager.CreateProcess("taskkill", $"/F /PID {processId}"))
221207
{
222-
taskkill.StartAndWaitAsync(tokenSource.Token, timeout)
208+
taskkill.StartAndWaitAsync(tokenSource.Token, confirmationWaitTime)
223209
.GetAwaiter().GetResult();
224210

225211
// 0 = Success

src/VirtualClient/VirtualClient.TestFramework/InMemoryProcess.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ public InMemoryProcess()
3535
/// </summary>
3636
public InMemoryProcess(Stream standardInput)
3737
{
38+
this.ExitCode = 0;
3839
this.StandardError = new ConcurrentBuffer();
3940
this.StandardOutput = new ConcurrentBuffer();
4041
this.StandardInput = new StreamWriter(standardInput);
@@ -45,6 +46,8 @@ public InMemoryProcess(Stream standardInput)
4546
};
4647
this.processDetails = new ProcessDetails();
4748
this.processDetails.Results = new List<string>();
49+
50+
this.OnHasExited = () => true;
4851
}
4952

5053
/// <summary>

0 commit comments

Comments
 (0)