@@ -8,17 +8,14 @@ namespace VirtualClient.Actions
88 using System . IO ;
99 using System . IO . Abstractions ;
1010 using System . Linq ;
11- using System . Runtime . InteropServices ;
1211 using System . Threading ;
1312 using System . Threading . Tasks ;
14- using Microsoft . AspNetCore . Http ;
15- using Microsoft . AspNetCore . Http . HttpResults ;
1613 using Microsoft . Extensions . DependencyInjection ;
14+ using Microsoft . Extensions . Logging ;
1715 using VirtualClient . Common ;
1816 using VirtualClient . Common . Extensions ;
1917 using VirtualClient . Common . Telemetry ;
2018 using VirtualClient . Contracts ;
21- using VirtualClient . Contracts . Metadata ;
2219
2320 /// <summary>
2421 /// The Prime95 workload executor.
@@ -27,7 +24,6 @@ namespace VirtualClient.Actions
2724 public class Prime95Executor : VirtualClientComponent
2825 {
2926 private IFileSystem fileSystem ;
30- private IPackageManager packageManager ;
3127 private ISystemManagement systemManagement ;
3228 private List < int > successExitCodes ;
3329
@@ -40,7 +36,6 @@ public Prime95Executor(IServiceCollection dependencies, IDictionary<string, ICon
4036 : base ( dependencies , parameters )
4137 {
4238 this . systemManagement = this . Dependencies . GetService < ISystemManagement > ( ) ;
43- this . packageManager = this . systemManagement . PackageManager ;
4439 this . fileSystem = this . systemManagement . FileSystem ;
4540
4641 // The exit code on SafeKill is -1 which is not a part of the default success codes.
@@ -163,7 +158,7 @@ public bool UseHyperthreading
163158 /// <summary>
164159 /// The path to the Prime95 workload package.
165160 /// </summary>
166- protected DependencyPath Prime95Package { get ; private set ; }
161+ protected DependencyPath WorkloadPackage { get ; private set ; }
167162
168163 /// <summary>
169164 /// Executes cleanup operations.
@@ -180,33 +175,37 @@ protected override async Task CleanupAsync(EventContext telemetryContext, Cancel
180175 {
181176 foreach ( IProcessProxy processProxy in runningProcesses )
182177 {
183- processProxy . SafeKill ( this . Logger ) ;
178+ try
179+ {
180+ processProxy . SafeKill ( ) ;
181+ }
182+ catch ( Exception exc )
183+ {
184+ // Best effort only but we want to log the issue for debugging/triage.
185+ this . Logger . LogMessage (
186+ $ "{ this . TypeName } .CleanupProcessError",
187+ LogLevel . Warning ,
188+ telemetryContext . Clone ( ) . AddError ( exc ) . AddContext ( "process" , processName ) ) ;
189+ }
184190 }
185191 }
186-
187- if ( this . fileSystem . File . Exists ( this . ResultsFilePath ) )
188- {
189- await this . fileSystem . File . DeleteAsync ( this . ResultsFilePath , RetryPolicies . FileDelete ) ;
190- }
191192 }
192193
193194 /// <summary>
194195 /// Initializes the environment for execution of the Prime95 workload.
195196 /// </summary>
196197 protected override async Task InitializeAsync ( EventContext telemetryContext , CancellationToken cancellationToken )
197198 {
198- await this . EvaluateParametersAsync ( cancellationToken ) ;
199-
200- this . Prime95Package = await this . GetPlatformSpecificPackageAsync ( this . PackageName , cancellationToken ) ;
199+ this . WorkloadPackage = await this . GetPlatformSpecificPackageAsync ( this . PackageName , cancellationToken ) ;
201200
202201 switch ( this . Platform )
203202 {
204203 case PlatformID . Win32NT :
205- this . ExecutablePath = this . Combine ( this . Prime95Package . Path , "prime95.exe" ) ;
204+ this . ExecutablePath = this . Combine ( this . WorkloadPackage . Path , "prime95.exe" ) ;
206205 break ;
207206
208207 case PlatformID . Unix :
209- this . ExecutablePath = this . Combine ( this . Prime95Package . Path , "mprime" ) ;
208+ this . ExecutablePath = this . Combine ( this . WorkloadPackage . Path , "mprime" ) ;
210209 break ;
211210
212211 default :
@@ -227,8 +226,8 @@ protected override async Task InitializeAsync(EventContext telemetryContext, Can
227226 ErrorReason . DependencyNotFound ) ;
228227 }
229228
230- this . SettingsFilePath = this . Combine ( this . GetTempPath ( ) , "prime.txt" ) ;
231- this . ResultsFilePath = this . Combine ( this . GetTempPath ( ) , FileContext . GetFileName ( "results.txt" , DateTime . UtcNow ) ) ;
229+ this . SettingsFilePath = this . Combine ( this . WorkloadPackage . Path , "prime.txt" ) ;
230+ this . ResultsFilePath = this . Combine ( this . WorkloadPackage . Path , "results.txt" ) ;
232231 }
233232
234233 /// <summary>
@@ -262,6 +261,13 @@ protected override void Validate()
262261 ErrorReason . InvalidProfileDefinition ) ;
263262 }
264263
264+ if ( this . MaxTortureFFT <= 0 )
265+ {
266+ throw new WorkloadException (
267+ $ "Invalid '{ nameof ( this . MaxTortureFFT ) } ' parameter value. The maximum torture FFT value must be greater than zero.",
268+ ErrorReason . InvalidProfileDefinition ) ;
269+ }
270+
265271 if ( this . MaxTortureFFT < this . MinTortureFFT )
266272 {
267273 throw new WorkloadException (
@@ -285,9 +291,9 @@ private async Task ExecuteWorkloadAsync(EventContext telemetryContext, Cancellat
285291
286292 await this . Logger . LogMessageAsync ( $ "{ this . TypeName } .ExecuteWorkload", telemetryContext , async ( ) =>
287293 {
288- using ( IProcessProxy process = this . systemManagement . ProcessManager . CreateProcess ( this . ExecutablePath , commandArguments , this . Prime95Package . Path ) )
294+ using ( IProcessProxy process = this . systemManagement . ProcessManager . CreateProcess ( this . ExecutablePath , commandArguments , this . WorkloadPackage . Path ) )
289295 {
290- this . CleanupTasks . Add ( ( ) => process . SafeKill ( this . Logger ) ) ;
296+ this . CleanupTasks . Add ( ( ) => process . SafeKill ( ) ) ;
291297
292298 // Prime95 does not stop on it's own. It will run until you tell it to stop.
293299 // We have to definitively stop the program.
@@ -296,36 +302,24 @@ await this.Logger.LogMessageAsync($"{this.TypeName}.ExecuteWorkload", telemetryC
296302 if ( process . Start ( ) )
297303 {
298304 await this . WaitAsync ( explicitTimeout , cancellationToken ) ;
299- process . SafeKill ( this . Logger ) ;
305+ process . SafeKill ( ) ;
300306
301307 if ( ! cancellationToken . IsCancellationRequested )
302308 {
303309 string results = null ;
304-
305- try
310+ if ( this . fileSystem . File . Exists ( this . ResultsFilePath ) )
306311 {
307- await RetryPolicies . FileOperations . ExecuteAsync ( async ( ) =>
308- {
309- if ( this . fileSystem . File . Exists ( this . ResultsFilePath ) )
310- {
311- results = await this . fileSystem . File . ReadAllTextAsync ( this . ResultsFilePath ) ;
312- }
313- } ) ;
314-
315- if ( string . IsNullOrWhiteSpace ( results ) )
316- {
317- throw new WorkloadResultsException (
318- $ "Prime95 results file not found at path '{ this . ResultsFilePath } '.",
319- ErrorReason . WorkloadResultsNotFound ) ;
320- }
321-
322- // The exit code on SafeKill is -1 which is not a part of the default success codes.
323- process . ThrowIfWorkloadFailed ( this . successExitCodes ) ;
324- this . CaptureMetrics ( process , results , telemetryContext , cancellationToken ) ;
312+ results = await this . fileSystem . File . ReadAllTextAsync ( this . ResultsFilePath ) ;
325313 }
326- finally
314+
315+ await this . LogProcessDetailsAsync ( process , telemetryContext , "Prime95" , results : results ? . AsArray ( ) ) ;
316+
317+ // The exit code on SafeKill is -1 which is not a part of the default success codes.
318+ process . ThrowIfWorkloadFailed ( this . successExitCodes ) ;
319+
320+ if ( ! string . IsNullOrWhiteSpace ( results ) )
327321 {
328- await this . LogProcessDetailsAsync ( process , telemetryContext , "Prime95" , results ? . AsArray ( ) ) ;
322+ this . CaptureMetrics ( process , results , telemetryContext , cancellationToken ) ;
329323 }
330324 }
331325 }
@@ -362,13 +356,6 @@ private void CaptureMetrics(IProcessProxy process, string results, EventContext
362356 {
363357 if ( ! cancellationToken . IsCancellationRequested )
364358 {
365- this . MetadataContract . AddForScenario (
366- "Prime95" ,
367- process . FullCommand ( ) ,
368- toolVersion : this . Prime95Package . Version ) ;
369-
370- this . MetadataContract . Apply ( telemetryContext ) ;
371-
372359 Prime95MetricsParser parser = new Prime95MetricsParser ( results ) ;
373360 IList < Metric > workloadMetrics = parser . Parse ( ) ;
374361
0 commit comments