Skip to content

Commit cbfd372

Browse files
committed
Address a range of bugs/issues. Metrics CSV flush on exit. Network workload to use scripts to configure network/firewall. Network profiles reference wrong package.
1 parent 4b1108a commit cbfd372

24 files changed

Lines changed: 999 additions & 504 deletions

File tree

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
2.1.58
1+
2.1.59

src/VirtualClient/VirtualClient.Actions/GeekBench/GeekbenchExecutor.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ protected override async Task InitializeAsync(EventContext telemetryContext, Can
164164
{
165165
try
166166
{
167-
await process.StartAndWaitAsync(cancellationToken, withExitConfirmation: true);
167+
await process.StartAndWaitAsync(cancellationToken);
168168

169169
if (!cancellationToken.IsCancellationRequested)
170170
{
@@ -261,7 +261,7 @@ private Task ExecuteWorkloadAsync(string pathToExe, string commandLineArguments,
261261
{
262262
try
263263
{
264-
await process.StartAndWaitAsync(cancellationToken, withExitConfirmation: true);
264+
await process.StartAndWaitAsync(cancellationToken);
265265

266266
if (!cancellationToken.IsCancellationRequested)
267267
{

src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/CPS/CPSExecutor.cs

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ namespace VirtualClient.Actions.NetworkPerformance
55
{
66
using System;
77
using System.Collections.Generic;
8-
using System.IO.Abstractions;
98
using System.Threading;
109
using System.Threading.Tasks;
1110
using Microsoft.Extensions.DependencyInjection;
@@ -22,17 +21,16 @@ namespace VirtualClient.Actions.NetworkPerformance
2221
/// </summary>
2322
public class CPSExecutor : NetworkingWorkloadToolExecutor
2423
{
25-
private IFileSystem fileSystem;
26-
2724
/// <summary>
2825
/// Initializes a new instance of the <see cref="CPSExecutor"/> class.
2926
/// </summary>
3027
/// <param name="component">Component to copy.</param>
3128
public CPSExecutor(VirtualClientComponent component)
3229
: base(component)
3330
{
34-
this.ProcessStartRetryPolicy = Policy.Handle<Exception>(exc => exc.Message.Contains("sockwiz")).Or<VirtualClientException>()
35-
.WaitAndRetryAsync(5, retries => TimeSpan.FromSeconds(retries * 3));
31+
this.ProcessStartRetryPolicy = Policy
32+
.Handle<Exception>()
33+
.WaitAndRetryAsync(3, retries => TimeSpan.FromSeconds(retries * 3));
3634
}
3735

3836
/// <summary>
@@ -43,9 +41,9 @@ public CPSExecutor(VirtualClientComponent component)
4341
public CPSExecutor(IServiceCollection dependencies, IDictionary<string, IConvertible> parameters)
4442
: base(dependencies, parameters)
4543
{
46-
this.fileSystem = dependencies.GetService<IFileSystem>();
47-
this.ProcessStartRetryPolicy = Policy.Handle<Exception>(exc => exc.Message.Contains("sockwiz")).Or<VirtualClientException>()
48-
.WaitAndRetryAsync(5, retries => TimeSpan.FromSeconds(retries * 3));
44+
this.ProcessStartRetryPolicy = Policy
45+
.Handle<Exception>()
46+
.WaitAndRetryAsync(3, retries => TimeSpan.FromSeconds(retries * 3));
4947
}
5048

5149
/// <summary>
@@ -274,7 +272,7 @@ await this.ProcessStartRetryPolicy.ExecuteAsync(async () =>
274272
try
275273
{
276274
this.CleanupTasks.Add(() => process.SafeKill(this.Logger));
277-
await process.StartAndWaitAsync(cancellationToken, timeout, withExitConfirmation: true);
275+
await process.StartAndWaitAsync(cancellationToken, timeout);
278276
await this.LogProcessDetailsAsync(process, relatedContext, "CPS");
279277
process.ThrowIfWorkloadFailed();
280278

src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/Latte/LatteClientExecutor.cs

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,10 +57,12 @@ await this.ProcessStartRetryPolicy.ExecuteAsync(async () =>
5757
{
5858
using (process = this.SystemManagement.ProcessManager.CreateProcess(this.ExecutablePath, commandArguments))
5959
{
60+
int processId = -1;
61+
6062
try
6163
{
62-
this.CleanupTasks.Add(() => process.SafeKill(this.Logger));
63-
await process.StartAndWaitAsync(cancellationToken, timeout, withExitConfirmation: true);
64+
await process.StartAndWaitAsync(cancellationToken, timeout);
65+
processId = process.Id;
6466

6567
if (!cancellationToken.IsCancellationRequested)
6668
{
@@ -80,14 +82,19 @@ await this.ProcessStartRetryPolicy.ExecuteAsync(async () =>
8082
// We give this a best effort but do not want it to prevent the next workload
8183
// from executing.
8284
this.Logger.LogMessage($"{this.GetType().Name}.WorkloadTimeout", LogLevel.Warning, relatedContext.AddError(exc));
83-
process.SafeKill(this.Logger);
8485
}
8586
catch (Exception exc)
8687
{
8788
this.Logger.LogMessage($"{this.GetType().Name}.WorkloadStartupError", LogLevel.Warning, relatedContext.AddError(exc));
88-
process.SafeKill(this.Logger);
8989
throw;
9090
}
91+
finally
92+
{
93+
if (processId > 0)
94+
{
95+
this.SystemManagement.ProcessManager.SafeKill(processId, this.Logger);
96+
}
97+
}
9198
}
9299
});
93100
}

src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/Latte/LatteExecutor.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,16 @@ namespace VirtualClient.Actions.NetworkPerformance
2020
[SupportedPlatforms("win-arm64,win-x64")]
2121
public class LatteExecutor : NetworkingWorkloadToolExecutor
2222
{
23-
private const string OutputFileName = "latte-results.xml";
24-
2523
/// <summary>
2624
/// Initializes a new instance of the <see cref="LatteExecutor"/> class.
2725
/// </summary>
2826
/// <param name="component">Component to copy.</param>
2927
public LatteExecutor(VirtualClientComponent component)
3028
: base(component)
3129
{
32-
this.ProcessStartRetryPolicy = Policy.Handle<Exception>(exc => exc.Message.Contains("sockwiz_tcp_listener_open bind"))
33-
.WaitAndRetryAsync(5, retries => TimeSpan.FromSeconds(retries * 3));
30+
this.ProcessStartRetryPolicy = Policy
31+
.Handle<Exception>()
32+
.WaitAndRetryAsync(3, retries => TimeSpan.FromSeconds(retries * 3));
3433
}
3534

3635
/// <summary>
@@ -41,8 +40,9 @@ public LatteExecutor(VirtualClientComponent component)
4140
public LatteExecutor(IServiceCollection dependencies, IDictionary<string, IConvertible> parameters)
4241
: base(dependencies, parameters)
4342
{
44-
this.ProcessStartRetryPolicy = Policy.Handle<Exception>(exc => exc.Message.Contains("sockwiz_tcp_listener_open bind"))
45-
.WaitAndRetryAsync(5, retries => TimeSpan.FromSeconds(retries * 3));
43+
this.ProcessStartRetryPolicy = Policy
44+
.Handle<Exception>()
45+
.WaitAndRetryAsync(3, retries => TimeSpan.FromSeconds(retries * 3));
4646
}
4747

4848
/// <summary>

src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/Latte/LatteServerExecutor.cs

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,8 +65,12 @@ await this.ProcessStartRetryPolicy.ExecuteAsync(async () =>
6565
}
6666
else
6767
{
68+
int processId = -1;
69+
6870
try
6971
{
72+
processId = process.Id;
73+
7074
// Wait until the cancellation token is signalled by the client.
7175
await this.WaitAsync(cancellationToken);
7276
process.Close();
@@ -80,9 +84,12 @@ await this.ProcessStartRetryPolicy.ExecuteAsync(async () =>
8084
}
8185
finally
8286
{
83-
// Latte must be explicitly terminated given the current implementation. If it is not,
84-
// the process will remain running in the background.
85-
process.SafeKill(this.Logger);
87+
if (processId > 0)
88+
{
89+
// Latte must be explicitly terminated given the current implementation. If it is not,
90+
// the process will remain running in the background.
91+
this.SystemManagement.ProcessManager.SafeKill(processId, this.Logger);
92+
}
8693
}
8794
}
8895
}

src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/NTttcp/NTttcpExecutor.cs

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,9 @@ public class NTttcpExecutor : NetworkingWorkloadToolExecutor
3434
public NTttcpExecutor(VirtualClientComponent component)
3535
: base(component)
3636
{
37-
this.ProcessStartRetryPolicy = Policy.Handle<Exception>(exc => exc.Message.Contains("sockwiz_tcp_listener_open bind"))
38-
.WaitAndRetryAsync(5, retries => TimeSpan.FromSeconds(retries * 3));
37+
this.ProcessStartRetryPolicy = Policy
38+
.Handle<Exception>()
39+
.WaitAndRetryAsync(3, retries => TimeSpan.FromSeconds(retries * 3));
3940
}
4041

4142
/// <summary>
@@ -46,8 +47,9 @@ public NTttcpExecutor(VirtualClientComponent component)
4647
public NTttcpExecutor(IServiceCollection dependencies, IDictionary<string, IConvertible> parameters)
4748
: base(dependencies, parameters)
4849
{
49-
this.ProcessStartRetryPolicy = Policy.Handle<Exception>(exc => exc.Message.Contains("sockwiz_tcp_listener_open bind"))
50-
.WaitAndRetryAsync(5, retries => TimeSpan.FromSeconds(retries * 3));
50+
this.ProcessStartRetryPolicy = Policy
51+
.Handle<Exception>()
52+
.WaitAndRetryAsync(3, retries => TimeSpan.FromSeconds(retries * 3));
5153
}
5254

5355
/// <summary>
@@ -330,7 +332,7 @@ await this.ProcessStartRetryPolicy.ExecuteAsync(async () =>
330332
try
331333
{
332334
this.CleanupTasks.Add(() => process.SafeKill(this.Logger));
333-
await process.StartAndWaitAsync(cancellationToken, timeout, withExitConfirmation: true);
335+
await process.StartAndWaitAsync(cancellationToken, timeout);
334336

335337
if (process.IsErrored())
336338
{

src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/SockPerf/SockPerfClientExecutor.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ namespace VirtualClient.Actions.NetworkPerformance
1111
using Microsoft.Extensions.DependencyInjection;
1212
using Microsoft.Extensions.Logging;
1313
using VirtualClient.Common;
14-
using VirtualClient.Common.Extensions;
1514
using VirtualClient.Common.Telemetry;
1615
using VirtualClient.Contracts;
1716
using VirtualClient.Contracts.Metadata;
@@ -62,8 +61,7 @@ await this.ProcessStartRetryPolicy.ExecuteAsync(async () =>
6261
{
6362
try
6463
{
65-
this.CleanupTasks.Add(() => process.SafeKill(this.Logger));
66-
await process.StartAndWaitAsync(cancellationToken, timeout, withExitConfirmation: true);
64+
await process.StartAndWaitAsync(cancellationToken, timeout);
6765

6866
if (!cancellationToken.IsCancellationRequested)
6967
{
@@ -91,14 +89,16 @@ await this.ProcessStartRetryPolicy.ExecuteAsync(async () =>
9189
// We give this a best effort but do not want it to prevent the next workload
9290
// from executing.
9391
this.Logger.LogMessage($"{this.TypeName}.WorkloadTimeout", LogLevel.Warning, relatedContext.AddError(exc));
94-
process.SafeKill(this.Logger);
9592
}
9693
catch (Exception exc)
9794
{
9895
this.Logger.LogMessage($"{this.TypeName}.WorkloadStartupError", LogLevel.Warning, relatedContext.AddError(exc));
99-
process.SafeKill(this.Logger);
10096
throw;
10197
}
98+
finally
99+
{
100+
process.SafeKill(this.Logger);
101+
}
102102
}
103103
});
104104
}

src/VirtualClient/VirtualClient.Actions/Network/NetworkingWorkload/SockPerf/SockPerfExecutor.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ public class SockPerfExecutor : NetworkingWorkloadToolExecutor
2929
public SockPerfExecutor(VirtualClientComponent component)
3030
: base(component)
3131
{
32-
this.ProcessStartRetryPolicy = Policy.Handle<Exception>(exc => exc.Message.Contains("sockwiz_tcp_listener_open bind"))
33-
.WaitAndRetryAsync(5, retries => TimeSpan.FromSeconds(retries * 3));
32+
this.ProcessStartRetryPolicy = Policy
33+
.Handle<Exception>()
34+
.WaitAndRetryAsync(3, retries => TimeSpan.FromSeconds(retries * 3));
3435
}
3536

3637
/// <summary>
@@ -41,8 +42,9 @@ public SockPerfExecutor(VirtualClientComponent component)
4142
public SockPerfExecutor(IServiceCollection dependencies, IDictionary<string, IConvertible> parameters)
4243
: base(dependencies, parameters)
4344
{
44-
this.ProcessStartRetryPolicy = Policy.Handle<Exception>(exc => exc.Message.Contains("sockwiz_tcp_listener_open bind"))
45-
.WaitAndRetryAsync(5, retries => TimeSpan.FromSeconds(retries * 3));
45+
this.ProcessStartRetryPolicy = Policy
46+
.Handle<Exception>()
47+
.WaitAndRetryAsync(3, retries => TimeSpan.FromSeconds(retries * 3));
4648
}
4749

4850
/// <summary>

src/VirtualClient/VirtualClient.Common/ProcessExtensions.cs

Lines changed: 2 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -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

Comments
 (0)