/// <summary> /// Check that the specified remote process's binary has a valid build id. Log messages and /// record metrics to indicate the result of the checks. /// </summary> /// <param name="pid">Process ID of the remote process that we will check</param> /// <param name="target">The machine that should have a valid remote binary</param> public async Task CheckRemoteBinaryOnAttachAsync(uint pid, SshTarget target, IAction action) { var remoteTargetPath = string.Format(PID_EXE_PATH_TEMPLATE, pid); try { var dataRecorder = new DataRecorder(action, DebugPreflightCheckData.Types.CheckType.AttachOnly); BuildId remoteBuildId; try { remoteBuildId = await binaryFileUtil.ReadBuildIdAsync(remoteTargetPath, target); } catch (BinaryFileUtilException e) when(dataRecorder.RemoteBuildIdError(e)) { Debug.Fail("Exception should never be caught"); throw; } // Log the remote Build ID for debugging purposes. dataRecorder.ValidRemoveBuildId(); Trace.WriteLine("Remote build ID: " + remoteBuildId.ToString()); } catch (BinaryFileUtilException e) { Trace.WriteLine($"Failed to read build ID for '{remoteTargetPath}' " + $"on '{target.GetString()}': " + e.ToString()); throw new PreflightBinaryCheckerException( ErrorStrings.FailedToCheckRemoteBuildIdWithExplanation(e.Message), e); } }
/// <summary> /// Check that the remote binary for the given executable exists and has a valid build id. /// Look for a local copy of the binary based on the name and build id. Log messages and /// record metrics to indicate the result of the checks. /// </summary> /// <remarks> /// It is assumed the remote binary is at YetiConstants.RemoteDeployPath. /// </remarks> /// <param name="libPaths">LLDB search paths to check for local binaries</param> /// <param name="executable">Name of the binary to look for locally and remotely</param> /// <param name="target">The machine that should have a valid remote binary</param> public async Task CheckLocalAndRemoteBinaryOnLaunchAsync( IEnumerable <string> libPaths, string executable, SshTarget target, string remoteTargetPath, IAction action) { // Check that the remote binary has a build id and try to match it against // the local candidates to find the matching local binary. IEnumerable <string> localCandidatePaths = new List <string>(); try { var dataRecorder = new DataRecorder(action, DebugPreflightCheckData.Types.CheckType.RunAndAttach); // Get the remote build id and only continue if this step succeeds. BuildId remoteBuildId; try { remoteBuildId = await binaryFileUtil.ReadBuildIdAsync(remoteTargetPath, target); } catch (BinaryFileUtilException e) when(dataRecorder.RemoteBuildIdError(e)) { Debug.Fail("Exception should never be caught"); throw; } // Log the remote Build ID for debugging purposes. dataRecorder.ValidRemoveBuildId(); Trace.WriteLine("Remote build ID: " + remoteBuildId.ToString()); // Make sure there is a local binary with the same name. localCandidatePaths = FindExecutableCandidates(libPaths, executable); if (!localCandidatePaths.Any()) { dataRecorder.LocalBinaryCheckResult( DebugPreflightCheckData.Types.LocalBinarySearchResult.NoCandidates); throw new NoLocalCandidatesException(); } // Check local candidates to find one matching the remote build id. // Ignore local candidates that are missing a build id. if (await HasMatchingBuildIdAsync( localCandidatePaths, executable, remoteTargetPath, remoteBuildId)) { dataRecorder.LocalBinaryCheckResult( DebugPreflightCheckData.Types.LocalBinarySearchResult.BinaryMatch); } else { dataRecorder.LocalBinaryCheckResult( DebugPreflightCheckData.Types.LocalBinarySearchResult.BinaryMismatch); throw new NoMatchingLocalCandidatesException(); } } catch (BinaryFileUtilException e) { Trace.WriteLine($"Failed to read build ID for '{remoteTargetPath}' " + $"on '{target.GetString()}': " + e.ToString()); throw new PreflightBinaryCheckerException( ErrorStrings.FailedToCheckRemoteBuildIdWithExplanation(e.Message), e); } catch (NoLocalCandidatesException e) { Trace.WriteLine($"Unable to find executable '{executable}' on LLDB search paths."); throw new PreflightBinaryCheckerException( ErrorStrings.UnableToFindExecutable(executable), ErrorStrings.ExecutableCheckDetails(libPaths), e); } catch (NoMatchingLocalCandidatesException e) { Trace.WriteLine( $"No local copy of '{executable}' matched the build ID of the remote binary"); throw new PreflightBinaryCheckerException( ErrorStrings.UnableToFindExecutableMatchingRemoteBinary(executable, remoteTargetPath), ErrorStrings.BuildIdCheckDetails(localCandidatePaths, libPaths), e); } }