Merged PR 682705: Enable nullable for SandboxedProcessInfo, SandboxedProcessFactory

This commit is contained in:
Erik Mavrinac 2022-10-10 19:48:37 +00:00
Родитель 3226a45ce1
Коммит c6ecf6f11c
7 изменённых файлов: 161 добавлений и 165 удалений

Просмотреть файл

@ -91,7 +91,11 @@ namespace BuildXL.Processes.Remoting
WorkingDirectory = m_processInfo!.WorkingDirectory,
};
remoteData.EnvironmentVariables.AddRange(m_processInfo!.EnvironmentVariables.ToDictionary());
if (m_processInfo!.EnvironmentVariables != null)
{
remoteData.EnvironmentVariables.AddRange(m_processInfo!.EnvironmentVariables.ToDictionary());
}
remoteData.FileDependencies.AddRange(ToStringPaths(m_fileDependencies));
remoteData.DirectoryDependencies.AddRange(ToStringPaths(m_directoryDependencies));
remoteData.OutputDirectories.AddRange(ToStringPaths(m_outputDirectories));

Просмотреть файл

@ -54,7 +54,7 @@ namespace BuildXL.Processes
private readonly PooledObjectWrapper<MemoryStream> m_fileAccessManifestStreamWrapper;
private MemoryStream FileAccessManifestStream => m_fileAccessManifestStreamWrapper.Instance;
private FileAccessManifest? m_fileAccessManifest;
private FileAccessManifest m_fileAccessManifest;
private readonly TaskSourceSlim<SandboxedProcessResult> m_resultTaskCompletionSource =
TaskSourceSlim.Create<SandboxedProcessResult>();
@ -67,7 +67,7 @@ namespace BuildXL.Processes
private SandboxedProcessOutputBuilder m_error;
private SandboxedProcessOutputBuilder m_output;
private readonly SandboxedProcessTraceBuilder? m_traceBuilder;
private SandboxedProcessReports? m_reports;
private SandboxedProcessReports m_reports;
private IAsyncPipeReader? m_reportReader;
private readonly SemaphoreSlim m_reportReaderSemaphore = TaskUtilities.CreateMutex();
private Dictionary<uint, ReportedProcess>? m_survivingChildProcesses;
@ -89,7 +89,6 @@ namespace BuildXL.Processes
{
Contract.Requires(!info.Timeout.HasValue || info.Timeout.Value <= Process.MaxTimeout);
Contract.Requires(!info.CreateSandboxTraceFile
|| info.FileAccessManifest == null
|| (info.FileAccessManifest.ReportFileAccesses && info.FileAccessManifest.LogProcessData && info.FileAccessManifest.ReportProcessArgs),
"Trace file is enabled, but some of the required options in the file access manifest are not.");
@ -139,8 +138,7 @@ namespace BuildXL.Processes
? new SandboxedProcessTraceBuilder(info.FileStorage, info.PathTable)
: null;
m_reports = m_fileAccessManifest != null ?
new SandboxedProcessReports(
m_reports = new SandboxedProcessReports(
m_fileAccessManifest,
info.PathTable,
info.PipSemiStableHash,
@ -149,7 +147,7 @@ namespace BuildXL.Processes
info.DetoursEventListener,
info.SidebandWriter,
info.FileSystemView,
m_traceBuilder) : null;
m_traceBuilder);
m_detouredProcess =
new DetouredProcess(
@ -171,7 +169,7 @@ namespace BuildXL.Processes
info.ContainerConfiguration,
// If there is any process configured to breakway from the sandbox, then we need to allow
// this to happen at the job object level
setJobBreakawayOk: m_fileAccessManifest?.ProcessesCanBreakaway ?? false,
setJobBreakawayOk: m_fileAccessManifest.ProcessesCanBreakaway,
info.CreateJobObjectForCurrentProcess,
info.DiagnosticsEnabled,
m_numRetriesPipeReadOnCancel,
@ -187,11 +185,6 @@ namespace BuildXL.Processes
/// <inheritdoc />
public int GetLastMessageCount()
{
if (m_reports == null)
{
return 0; // We didn't count the messages.
}
return m_reports.GetLastMessageCount();
}
@ -392,12 +385,7 @@ namespace BuildXL.Processes
/// <inheritdoc />
public long GetDetoursMaxHeapSize()
{
if (m_reports != null)
{
return m_reports.MaxDetoursHeapSize;
}
return 0L;
return m_reports.MaxDetoursHeapSize;
}
/// <summary>
@ -426,8 +414,6 @@ namespace BuildXL.Processes
m_output.Dispose();
m_error.Dispose();
m_reports = null;
m_fileAccessManifestStreamWrapper.Dispose();
}
@ -505,11 +491,7 @@ namespace BuildXL.Processes
bool debugFlagsMatch = true;
ArraySegment<byte> manifestBytes = new ArraySegment<byte>();
if (m_fileAccessManifest != null)
{
manifestBytes = m_fileAccessManifest.GetPayloadBytes(m_loggingContext, setup, FileAccessManifestStream, m_timeoutMins, ref debugFlagsMatch);
}
manifestBytes = m_fileAccessManifest.GetPayloadBytes(m_loggingContext, setup, FileAccessManifestStream, m_timeoutMins, ref debugFlagsMatch);
if (!debugFlagsMatch)
{
throw new BuildXLException("Mismatching build type for BuildXL and DetoursServices.dll.");
@ -544,14 +526,11 @@ namespace BuildXL.Processes
}
string memUsage = $"RamPercent: {ramPercent}, AvailableRamMb: {availableRamMb}, AvailablePageFileMb: {availablePageFileMb}, TotalPageFileMb: {totalPageFileMb}";
Native.Tracing.Logger.Log.DetouredProcessAccessViolationException(m_loggingContext, (m_reports?.PipDescription ?? "") + " - " + memUsage);
Native.Tracing.Logger.Log.DetouredProcessAccessViolationException(m_loggingContext, m_reports.PipDescription + " - " + memUsage);
throw;
}
finally
{
// release memory
m_fileAccessManifest = null;
// Note that in the success path, childHandle should already be closed (by Start).
if (childHandle != null && !childHandle.IsInvalid)
{
@ -559,13 +538,13 @@ namespace BuildXL.Processes
}
}
StreamDataReceived? reportLineReceivedCallback = m_reports == null ? null : ReportLineReceived;
StreamDataReceived reportLineReceivedCallback = ReportLineReceived;
if (useManagedPipeReader)
{
m_reportReader = PipeReaderFactory.CreateManagedPipeReader(
pipeStream,
message => reportLineReceivedCallback?.Invoke(message) ?? true,
message => reportLineReceivedCallback(message),
reportEncoding,
m_bufferSize);
}
@ -597,11 +576,11 @@ namespace BuildXL.Processes
SandboxedProcessFactory.Counters.IncrementCounter(SandboxedProcessFactory.SandboxedProcessCounters.AccessReportCount);
using (SandboxedProcessFactory.Counters.StartStopwatch(SandboxedProcessFactory.SandboxedProcessCounters.HandleAccessReportDuration))
{
return m_reports!.ReportLineReceived(data);
return m_reports.ReportLineReceived(data);
}
}
private void DebugPipeConnection(string data) => m_reports?.ReportLineReceived($"{(int)ReportType.DebugMessage},{data}");
private void DebugPipeConnection(string data) => m_reports.ReportLineReceived($"{(int)ReportType.DebugMessage},{data}");
private static async Task FeedStandardInputAsync(DetouredProcess detouredProcess, TextReader? reader, TaskSourceSlim<bool> stdInTcs)
{
@ -672,7 +651,7 @@ namespace BuildXL.Processes
await WaitUntilReportEof(m_detouredProcess!.Killed);
// Ensure no further modifications to the report
m_reports?.Freeze();
m_reports.Freeze();
// We can get extended accounting information (peak memory, etc. rolled up for the entire process tree) if this process was wrapped in a job.
JobObject.AccountingInformation? jobAccountingInformation = null;
@ -713,7 +692,7 @@ namespace BuildXL.Processes
// Construct result; note that the process is expected to have exited at this point, even if we decided to forcefully kill it
// (this callback is always a result of the process handle being signaled).
int exitCode = 0;
if (m_reports?.MessageProcessingFailure != null)
if (m_reports.MessageProcessingFailure != null)
{
exitCode = ExitCodes.MessageProcessingFailure;
}
@ -737,17 +716,17 @@ namespace BuildXL.Processes
StandardOutput = m_output.Freeze(),
StandardError = m_error.Freeze(),
TraceFile = m_traceBuilder?.Freeze(),
AllUnexpectedFileAccesses = m_reports?.FileUnexpectedAccesses,
FileAccesses = m_reports?.FileAccesses,
DetouringStatuses = m_reports?.ProcessDetoursStatuses,
ExplicitlyReportedFileAccesses = m_reports?.ExplicitlyReportedFileAccesses,
Processes = m_reports?.Processes,
AllUnexpectedFileAccesses = m_reports.FileUnexpectedAccesses,
FileAccesses = m_reports.FileAccesses,
DetouringStatuses = m_reports.ProcessDetoursStatuses,
ExplicitlyReportedFileAccesses = m_reports.ExplicitlyReportedFileAccesses,
Processes = m_reports.Processes,
DumpFileDirectory = m_detouredProcess.DumpFileDirectory,
DumpCreationException = m_detouredProcess.DumpCreationException,
StandardInputException = standardInputException,
MessageProcessingFailure = m_reports?.MessageProcessingFailure,
MessageProcessingFailure = m_reports.MessageProcessingFailure,
ProcessStartTime = m_detouredProcess.StartTime,
HasReadWriteToReadFileAccessRequest = m_reports?.HasReadWriteToReadFileAccessRequest ?? false,
HasReadWriteToReadFileAccessRequest = m_reports.HasReadWriteToReadFileAccessRequest,
DiagnosticMessage = m_detouredProcess.Diagnostics
};

Просмотреть файл

@ -14,6 +14,8 @@ using BuildXL.Utilities.Instrumentation.Common;
using BuildXL.Utilities.Tracing;
using static BuildXL.Tracing.Diagnostics;
#nullable enable
namespace BuildXL.Processes
{
/// <summary>
@ -224,7 +226,7 @@ namespace BuildXL.Processes
public static readonly CounterCollection<SandboxedProcessCounters> Counters = new ();
/// <summary>
/// Start a sand-boxed process asynchronously. The result will only be available once the process terminates.
/// Start a sandboxed process asynchronously. The result will only be available once the process terminates.
/// </summary>
/// <exception cref="BuildXLException">
/// Thrown if the process creation fails in a recoverable manner due do some obscure problem detected by the underlying
@ -233,12 +235,13 @@ namespace BuildXL.Processes
[SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Object lives on via task result.")]
public static Task<ISandboxedProcess> StartAsync(SandboxedProcessInfo info, bool forceSandboxing)
{
Contract.Requires(info != null);
Contract.Requires(info.FileName != null);
Contract.Requires(info.LoggingContext != null);
Contract.Requires(
info.GetCommandLine().Length <= SandboxedProcessInfo.MaxCommandLineLength,
$"Command line's length ({info.GetCommandLine().Length}) exceeds the max length {SandboxedProcessInfo.MaxCommandLineLength}");
string cmdLine = info.GetCommandLine();
if (cmdLine.Length > SandboxedProcessInfo.MaxCommandLineLength)
{
Contract.Requires(
cmdLine.Length <= SandboxedProcessInfo.MaxCommandLineLength,
$"Command line's length ({cmdLine.Length}) exceeds the max length {SandboxedProcessInfo.MaxCommandLineLength}");
}
if (info.TestRetries)
{
@ -284,12 +287,12 @@ namespace BuildXL.Processes
/// This is a separate function and not inlined as an anonymous delegate, as VS seems to have trouble with those when
/// measuring code coverage
/// </remarks>
private static ISandboxedProcess ProcessStart(object state)
private static ISandboxedProcess ProcessStart(object? state)
{
Counters.IncrementCounter(SandboxedProcessCounters.SandboxedProcessCount);
var stateTuple = (Tuple<SandboxedProcessInfo, bool>)state;
var stateTuple = (Tuple<SandboxedProcessInfo, bool>)state!;
SandboxedProcessInfo info = stateTuple.Item1;
ISandboxedProcess result = null;
ISandboxedProcess? result = null;
try
{
result = Create(info, forceSandboxing: stateTuple.Item2);

Просмотреть файл

@ -17,6 +17,8 @@ using CanBeNullAttribute = JetBrains.Annotations.CanBeNullAttribute;
using static BuildXL.Utilities.BuildParameters;
using BuildXL.Processes.Remoting;
#nullable enable
namespace BuildXL.Processes
{
/// <summary>
@ -62,13 +64,13 @@ namespace BuildXL.Processes
/// </remarks>
public static readonly TimeSpan DefaultNestedProcessTerminationTimeout = TimeSpan.FromSeconds(30);
private string m_arguments;
private string? m_arguments;
private string m_commandLine;
private string? m_commandLine;
private byte[] m_environmentBlock;
private byte[]? m_environmentBlock;
private string m_rootMappingBlock;
private string? m_rootMappingBlock;
private int m_maxLengthInMemory = 16384;
@ -80,22 +82,22 @@ namespace BuildXL.Processes
/// <summary>
/// A detours event listener.
/// </summary>
public IDetoursEventListener DetoursEventListener { get; private set; }
public IDetoursEventListener? DetoursEventListener { get; private set; }
/// <summary>
/// A macOS kernel extension connection.
/// </summary>
public ISandboxConnection SandboxConnection;
public ISandboxConnection? SandboxConnection;
/// <summary>
/// An optional shared opaque output logger to use to record file writes under shared opaque directories as soon as they happen.
/// </summary>
public SidebandWriter SidebandWriter { get; }
public SidebandWriter? SidebandWriter { get; }
/// <summary>
/// An optional file system view to report outputs as soon as they are produced
/// </summary>
public ISandboxFileSystemView FileSystemView { get; }
public ISandboxFileSystemView? FileSystemView { get; }
/// <summary>
/// Whether the process creating a <see cref="SandboxedProcess"/> gets added to a job object
@ -113,7 +115,7 @@ namespace BuildXL.Processes
/// <summary>
/// Indicates whether resource usage of the sandboxed process tree should be measured and logged for later inspection.
/// </summary>
public SandboxedProcessResourceMonitoringConfig MonitoringConfig;
public SandboxedProcessResourceMonitoringConfig? MonitoringConfig { get; set; }
/// <summary>
/// Holds the path remapping information for a process that needs to run in a container
@ -131,15 +133,15 @@ namespace BuildXL.Processes
/// compile against this assembly and already depend on this constructor.
/// </remarks>
public SandboxedProcessInfo(
[CanBeNull] ISandboxedProcessFileStorage fileStorage,
ISandboxedProcessFileStorage? fileStorage,
string fileName,
bool disableConHostSharing,
bool testRetries = false,
LoggingContext loggingContext = null,
IDetoursEventListener detoursEventListener = null,
ISandboxConnection sandboxConnection = null,
LoggingContext? loggingContext = null,
IDetoursEventListener? detoursEventListener = null,
ISandboxConnection? sandboxConnection = null,
bool createJobObjectForCurrentProcess = true,
SandboxedProcessResourceMonitoringConfig monitoringConfig = null)
SandboxedProcessResourceMonitoringConfig? monitoringConfig = null)
: this(
new PathTable(),
fileStorage,
@ -159,25 +161,22 @@ namespace BuildXL.Processes
/// </summary>
public SandboxedProcessInfo(
PathTable pathTable,
[CanBeNull] ISandboxedProcessFileStorage fileStorage,
ISandboxedProcessFileStorage? fileStorage,
string fileName,
FileAccessManifest fileAccessManifest,
FileAccessManifest? fileAccessManifest,
bool disableConHostSharing,
ContainerConfiguration containerConfiguration,
LoggingContext loggingContext,
bool testRetries = false,
IDetoursEventListener detoursEventListener = null,
ISandboxConnection sandboxConnection = null,
SidebandWriter sidebandWriter = null,
IDetoursEventListener? detoursEventListener = null,
ISandboxConnection? sandboxConnection = null,
SidebandWriter? sidebandWriter = null,
bool createJobObjectForCurrentProcess = true,
ISandboxFileSystemView fileSystemView = null,
SandboxedProcessResourceMonitoringConfig monitoringConfig = null)
ISandboxFileSystemView? fileSystemView = null,
SandboxedProcessResourceMonitoringConfig? monitoringConfig = null)
{
Contract.RequiresNotNull(pathTable);
Contract.RequiresNotNull(fileName);
PathTable = pathTable;
FileAccessManifest = fileAccessManifest;
FileAccessManifest = fileAccessManifest ?? new FileAccessManifest(pathTable);
FileStorage = fileStorage;
FileName = fileName;
DisableConHostSharing = disableConHostSharing;
@ -201,23 +200,23 @@ namespace BuildXL.Processes
/// </summary>
public SandboxedProcessInfo(
PathTable pathTable,
[CanBeNull] ISandboxedProcessFileStorage fileStorage,
ISandboxedProcessFileStorage? fileStorage,
string fileName,
bool disableConHostSharing,
LoggingContext loggingContext,
bool testRetries = false,
IDetoursEventListener detoursEventListener = null,
ISandboxConnection sandboxConnection = null,
ContainerConfiguration containerConfiguration = null,
FileAccessManifest fileAccessManifest = null,
IDetoursEventListener? detoursEventListener = null,
ISandboxConnection? sandboxConnection = null,
ContainerConfiguration? containerConfiguration = null,
FileAccessManifest? fileAccessManifest = null,
bool createJobObjectForCurrentProcess = true,
SandboxedProcessResourceMonitoringConfig monitoringConfig = null
SandboxedProcessResourceMonitoringConfig? monitoringConfig = null
)
: this(
pathTable,
fileStorage,
fileName,
fileAccessManifest ?? new FileAccessManifest(pathTable),
fileAccessManifest,
disableConHostSharing,
containerConfiguration ?? ContainerConfiguration.DisabledIsolation,
loggingContext,
@ -227,8 +226,6 @@ namespace BuildXL.Processes
createJobObjectForCurrentProcess: createJobObjectForCurrentProcess,
monitoringConfig: monitoringConfig)
{
Contract.RequiresNotNull(pathTable);
Contract.RequiresNotNull(fileName);
}
/// <summary>
@ -250,7 +247,7 @@ namespace BuildXL.Processes
/// <summary>
/// Optional file storage options for stdout and stderr output streams.
/// </summary>
public ISandboxedProcessFileStorage FileStorage { get; }
public ISandboxedProcessFileStorage? FileStorage { get; }
/// <summary>
/// When stdout or stderr are redirected and this flag is true, disables sharing of the instance of
@ -281,17 +278,17 @@ namespace BuildXL.Processes
/// <summary>
/// How to decode the standard input; if not set, encoding of current process is used
/// </summary>
public Encoding StandardInputEncoding { get; set; }
public Encoding? StandardInputEncoding { get; set; }
/// <summary>
/// How to decode the standard output; if not set, encoding of current process is used
/// </summary>
public Encoding StandardErrorEncoding { get; set; }
public Encoding? StandardErrorEncoding { get; set; }
/// <summary>
/// How to decode the standard output; if not set, encoding of current process is used
/// </summary>
public Encoding StandardOutputEncoding { get; set; }
public Encoding? StandardOutputEncoding { get; set; }
/// <summary>
/// Number of pipe reading retries on cancellation.
@ -310,7 +307,7 @@ namespace BuildXL.Processes
/// <summary>
/// Encoded command line arguments
/// </summary>
public string Arguments
public string? Arguments
{
get
{
@ -327,7 +324,7 @@ namespace BuildXL.Processes
/// <summary>
/// Working directory (can be null)
/// </summary>
public string WorkingDirectory { get; set; }
public string? WorkingDirectory { get; set; }
/// <summary>
/// Root jail information (can be null)
@ -340,37 +337,37 @@ namespace BuildXL.Processes
/// <summary>
/// Environment variables (can be null)
/// </summary>
public IBuildParameters EnvironmentVariables { get; set; }
public IBuildParameters? EnvironmentVariables { get; set; }
/// <summary>
/// Root drive remappings (can be null)
/// </summary>
public IReadOnlyDictionary<string, string> RootMappings { get; set; }
public IReadOnlyDictionary<string, string>? RootMappings { get; set; }
/// <summary>
/// Optional standard input stream from which to read
/// </summary>
public TextReader StandardInputReader { get; set; }
public TextReader? StandardInputReader { get; set; }
/// <summary>
/// Optional observer of each output line
/// </summary>
public Action<string> StandardOutputObserver { get; set; }
public Action<string>? StandardOutputObserver { get; set; }
/// <summary>
/// Optional observer of each output line
/// </summary>
public Action<string> StandardErrorObserver { get; set; }
public Action<string>? StandardErrorObserver { get; set; }
/// <summary>
/// Allowed surviving child processes.
/// </summary>
public string[] AllowedSurvivingChildProcessNames { get; set; }
public string[]? AllowedSurvivingChildProcessNames { get; set; }
/// <summary>
/// Temp folder redirection.
/// </summary>
public (string source, string target)[] RedirectedTempFolders { get; set; }
public (string source, string target)[]? RedirectedTempFolders { get; set; }
/// <summary>
/// Max. number of characters buffered in memory before output is streamed to disk
@ -397,7 +394,7 @@ namespace BuildXL.Processes
/// <summary>
/// File where Detours log failure message, e.g., communication failure, injection failure, etc.
/// </summary>
public string DetoursFailureFile { get; set; }
public string? DetoursFailureFile { get; set; }
/// <summary>
/// Gets the command line, comprised of the executable file name and the arguments.
@ -414,7 +411,7 @@ namespace BuildXL.Processes
/// </summary>
public string GetUnicodeRootMappingBlock()
{
IReadOnlyDictionary<string, string> rootMappings = RootMappings;
IReadOnlyDictionary<string, string>? rootMappings = RootMappings;
if (rootMappings == null)
{
return string.Empty;
@ -445,7 +442,7 @@ namespace BuildXL.Processes
/// <summary>
/// Gets the current environment variables, if any, as a unicode environment block
/// </summary>
public byte[] GetUnicodeEnvironmentBlock()
public byte[]? GetUnicodeEnvironmentBlock()
{
return m_environmentBlock ??= ProcessUtilities.SerializeEnvironmentBlock(EnvironmentVariables?.ToDictionary());
}
@ -472,12 +469,12 @@ namespace BuildXL.Processes
/// Root directory where timeout dumps for the process should be stored. This directory may contain other outputs
/// for the process.
/// </summary>
public string TimeoutDumpDirectory { get; set; }
public string? TimeoutDumpDirectory { get; set; }
/// <summary>
/// Root directory where surviving child process dumps should be saved
/// </summary>
public string SurvivingPipProcessChildrenDumpDirectory { get; set; }
public string? SurvivingPipProcessChildrenDumpDirectory { get; set; }
/// <summary>
/// The kind of sandboxing to use.
@ -487,7 +484,7 @@ namespace BuildXL.Processes
/// <summary>
/// Pip's Description. Used for logging.
/// </summary>
public string PipDescription { get; set; }
public string? PipDescription { get; set; }
/// <summary>
/// Standard output and error options for the sandboxed process.
@ -495,7 +492,7 @@ namespace BuildXL.Processes
/// <remarks>
/// This instance of <see cref="SandboxedProcessStandardFiles"/> is used as an alternative to <see cref="FileStorage"/>.
/// </remarks>
public SandboxedProcessStandardFiles SandboxedProcessStandardFiles { get; set; }
public SandboxedProcessStandardFiles? SandboxedProcessStandardFiles { get; set; }
/// <summary>
/// Info about the source of standard input.
@ -503,7 +500,7 @@ namespace BuildXL.Processes
/// <remarks>
/// This instance of <see cref="StandardInputInfo"/> is used as a serialized version of <see cref="StandardInputReader"/>.
/// </remarks>
public StandardInputInfo StandardInputSourceInfo { get; set; }
public StandardInputInfo? StandardInputSourceInfo { get; set; }
/// <summary>
/// Observer descriptor.
@ -511,7 +508,7 @@ namespace BuildXL.Processes
/// <remarks>
/// This instance of <see cref="SandboxObserverDescriptor"/> is used as a serialized version of <see cref="StandardOutputObserver"/> and <see cref="StandardErrorObserver"/>.
/// </remarks>
public SandboxObserverDescriptor StandardObserverDescriptor { get; set; }
public SandboxObserverDescriptor? StandardObserverDescriptor { get; set; }
/// <summary>
/// Provenance description.
@ -526,13 +523,19 @@ namespace BuildXL.Processes
/// <summary>
/// Extra data for executing a pip in an external VM.
/// </summary>
public ExternalVMSandboxedProcessData ExternalVMSandboxedProcessData { get; set; }
public ExternalVMSandboxedProcessData? ExternalVMSandboxedProcessData { get; set; }
/// <summary>
/// Whether to create a sandbox trace file.
/// </summary>
public bool CreateSandboxTraceFile { get; init; }
/// <summary>
/// An optional existing Windows job object handle to use for this process.
/// The job object handle will not be closed automatically and must be closed by the caller.
/// </summary>
public IntPtr PreExistingJobObjectOrZero { get; init; }
#region Serialization
/// <nodoc />
@ -552,7 +555,7 @@ namespace BuildXL.Processes
writer.Write(
EnvironmentVariables,
(w, v) => w.WriteReadOnlyList(
v.ToDictionary().ToList(),
v!.ToDictionary().ToList(),
(w2, kvp) =>
{
w2.Write(kvp.Key);
@ -586,17 +589,17 @@ namespace BuildXL.Processes
SandboxedProcessStandardFiles.Serialize(writer);
}
writer.Write(StandardInputSourceInfo, (w, v) => v.Serialize(w));
writer.Write(StandardObserverDescriptor, (w, v) => v.Serialize(w));
writer.Write(StandardInputSourceInfo, (w, v) => v!.Serialize(w));
writer.Write(StandardObserverDescriptor, (w, v) => v!.Serialize(w));
writer.Write(NumRetriesPipeReadOnCancel);
writer.Write(
RedirectedTempFolders,
(w, v) => w.WriteReadOnlyList(v, (w2, v2) => { w2.Write(v2.source); w2.Write(v2.target); }));
writer.Write(SidebandWriter, (w, v) => v.Serialize(w));
writer.Write(SidebandWriter, (w, v) => v!.Serialize(w));
writer.Write(CreateJobObjectForCurrentProcess);
writer.WriteNullableString(DetoursFailureFile);
writer.Write(ExternalVMSandboxedProcessData, (w, v) => v.Serialize(w));
writer.Write(ExternalVMSandboxedProcessData, (w, v) => v!.Serialize(w));
writer.Write(CreateSandboxTraceFile);
// File access manifest should be serialized the last.
@ -605,41 +608,41 @@ namespace BuildXL.Processes
}
/// <nodoc />
public static SandboxedProcessInfo Deserialize(Stream stream, LoggingContext loggingContext, IDetoursEventListener detoursEventListener)
public static SandboxedProcessInfo Deserialize(Stream stream, LoggingContext loggingContext, IDetoursEventListener? detoursEventListener)
{
using (var reader = new BuildXLReader(false, stream, true))
{
string arguments = reader.ReadNullableString();
string commandLine = reader.ReadNullableString();
string? arguments = reader.ReadNullableString();
string? commandLine = reader.ReadNullableString();
bool disableConHostSharing = reader.ReadBoolean();
string fileName = reader.ReadNullableString();
Encoding standardInputEncoding = reader.ReadNullable(r => r.ReadEncoding());
Encoding standardOutputEncoding = reader.ReadNullable(r => r.ReadEncoding());
Encoding standardErrorEncoding = reader.ReadNullable(r => r.ReadEncoding());
string workingDirectory = reader.ReadNullableString();
string? fileName = reader.ReadNullableString();
Encoding? standardInputEncoding = reader.ReadNullable(r => r.ReadEncoding());
Encoding? standardOutputEncoding = reader.ReadNullable(r => r.ReadEncoding());
Encoding? standardErrorEncoding = reader.ReadNullable(r => r.ReadEncoding());
string? workingDirectory = reader.ReadNullableString();
RootJailInfo? rootJailInfo = reader.ReadNullableStruct(r => BuildXL.Processes.RootJailInfo.Deserialize(r));
IBuildParameters buildParameters = null;
IBuildParameters? buildParameters = null;
var envVars = reader.ReadNullable(r => r.ReadReadOnlyList(r2 => new KeyValuePair<string, string>(r2.ReadString(), r2.ReadString())));
if (envVars != null)
{
buildParameters = BuildParameters.GetFactory().PopulateFromDictionary(envVars.ToDictionary(kvp => kvp.Key, kvp => kvp.Value));
}
string[] allowedSurvivingChildNames = reader.ReadNullable(r => r.ReadReadOnlyList(r2 => r2.ReadString()))?.ToArray();
string[]? allowedSurvivingChildNames = reader.ReadNullable(r => r.ReadReadOnlyList(r2 => r2.ReadString()))?.ToArray();
int maxLengthInMemory = reader.ReadInt32();
TimeSpan? timeout = reader.ReadNullableStruct(r => r.ReadTimeSpan());
TimeSpan nestedProcessTerminationTimeout = reader.ReadTimeSpan();
long pipSemiStableHash = reader.ReadInt64();
string timeoutDumpDirectory = reader.ReadNullableString();
string survivingPipProcessChildrenDumpDirectory = reader.ReadNullableString();
string? timeoutDumpDirectory = reader.ReadNullableString();
string? survivingPipProcessChildrenDumpDirectory = reader.ReadNullableString();
SandboxKind sandboxKind = (SandboxKind)reader.ReadByte();
string pipDescription = reader.ReadNullableString();
string? pipDescription = reader.ReadNullableString();
SandboxedProcessStandardFiles sandboxedProcessStandardFiles = SandboxedProcessStandardFiles.Deserialize(reader);
StandardInputInfo standardInputSourceInfo = reader.ReadNullable(r => StandardInputInfo.Deserialize(r));
SandboxObserverDescriptor standardObserverDescriptor = reader.ReadNullable(r => SandboxObserverDescriptor.Deserialize(r));
StandardInputInfo? standardInputSourceInfo = reader.ReadNullable(r => StandardInputInfo.Deserialize(r));
SandboxObserverDescriptor? standardObserverDescriptor = reader.ReadNullable(r => SandboxObserverDescriptor.Deserialize(r));
int numRetriesPipeReadOnCancel = reader.ReadInt32();
(string source, string target)[] redirectedTempFolder = reader.ReadNullable(r => r.ReadReadOnlyList(r2 => (source: r2.ReadString(), target: r2.ReadString())))?.ToArray();
(string source, string target)[]? redirectedTempFolder = reader.ReadNullable(r => r.ReadReadOnlyList(r2 => (source: r2.ReadString(), target: r2.ReadString())))?.ToArray();
var sidebandWritter = reader.ReadNullable(r => SidebandWriter.Deserialize(r));
var createJobObjectForCurrentProcess = reader.ReadBoolean();

Просмотреть файл

@ -86,7 +86,7 @@ namespace BuildXL.Processes
/// <summary>
/// Allowed surviving child process names.
/// </summary>
private string[] AllowedSurvivingChildProcessNames { get; }
private string[]? AllowedSurvivingChildProcessNames { get; }
private bool IgnoreReportedAccesses { get; }
@ -151,7 +151,7 @@ namespace BuildXL.Processes
PipId = info.FileAccessManifest.PipId;
SandboxConnection = info.SandboxConnection;
SandboxConnection = info.SandboxConnection!;
ChildProcessTimeout = info.NestedProcessTerminationTimeout;
AllowedSurvivingChildProcessNames = info.AllowedSurvivingChildProcessNames;
ReportQueueProcessTimeoutForTests = info.ReportQueueProcessTimeoutForTests;
@ -268,9 +268,14 @@ namespace BuildXL.Processes
// inside the jail, run "bxl-env" to change into user-specified directory as well as to set environment variables before running user-specified program
// NOTE: -C <dir> must be the first two arguments, see bxl-env.c
process.StartInfo.ArgumentList.Add(info.RootJailInfo.CopyToRootJailIfNeeded(EnvExecutable));
// change directory into what the user specified
process.StartInfo.ArgumentList.Add("-C");
process.StartInfo.ArgumentList.Add(info.WorkingDirectory);
if (info.WorkingDirectory != null)
{
// change directory into what the user specified
process.StartInfo.ArgumentList.Add("-C");
process.StartInfo.ArgumentList.Add(info.WorkingDirectory);
}
// propagate environment variables (because root jail program won't do it)
process.StartInfo.ArgumentList.Add("-i");
foreach (var kvp in process.StartInfo.Environment.Select(kvp => (kvp.Key, kvp.Value)).Concat(AdditionalEnvVars(info)))
@ -292,7 +297,7 @@ namespace BuildXL.Processes
// When executed using external tool, the manifest tree has been sealed, and cannot be modified.
// We take care of adding this path in the manifest in SandboxedProcessPipExecutor.cs;
// see AddUnixSpecificSandcboxedProcessFileAccessPolicies
if (!info.FileAccessManifest.IsManifestTreeBlockSealed)
if (!info.FileAccessManifest!.IsManifestTreeBlockSealed)
{
info.FileAccessManifest.AddPath(
AbsolutePath.Create(PathTable, process.StartInfo.FileName),
@ -355,7 +360,7 @@ namespace BuildXL.Processes
// NOTE: just by not keeping any references to 'info' should make the FileAccessManifest object
// unreachable and thus available for garbage collection. We call Release() here explicitly
// just to emphasize the importance of reclaiming this memory.
info.FileAccessManifest.Release();
info.FileAccessManifest!.Release();
}
}
@ -517,7 +522,7 @@ namespace BuildXL.Processes
m_pendingReports.Post(report);
}
private static string? EnsureQuoted(string cmdLineArgs)
private static string? EnsureQuoted(string? cmdLineArgs)
{
#if NETCOREAPP
if (cmdLineArgs == null)
@ -584,7 +589,7 @@ namespace BuildXL.Processes
lines.Add("set -e");
if (info.SandboxConnection.Kind == SandboxKind.MacOsHybrid || info.SandboxConnection.Kind == SandboxKind.MacOsDetours)
if (info.SandboxConnection!.Kind == SandboxKind.MacOsHybrid || info.SandboxConnection.Kind == SandboxKind.MacOsDetours)
{
lines.Add($"export {DetoursEnvVar}={DetoursFile}");
}
@ -608,7 +613,7 @@ namespace BuildXL.Processes
private IEnumerable<(string, string?)> AdditionalEnvVars(SandboxedProcessInfo info)
{
return info.SandboxConnection
return info.SandboxConnection!
.AdditionalEnvVarsToSet(info, UniqueName)
.Concat(info.SandboxConnection.Kind == SandboxKind.MacOsHybrid || info.SandboxConnection.Kind == SandboxKind.MacOsDetours
? new (string, string?)[] { (DetoursEnvVar, DetoursFile) }
@ -905,7 +910,7 @@ namespace BuildXL.Processes
// When executed using external tool, the manifest tree has been sealed, and cannot be modified.
// We take care of adding this path in the manifest in SandboxedProcessPipExecutor.cs;
// see AddUnixSpecificSandcboxedProcessFileAccessPolicies
if (!info.FileAccessManifest.IsManifestTreeBlockSealed)
if (!info.FileAccessManifest!.IsManifestTreeBlockSealed)
{
info.FileAccessManifest.AddPath(
AbsolutePath.Create(PathTable, stdinFileName),

Просмотреть файл

@ -143,9 +143,9 @@ namespace BuildXL.Processes
PipDescription = info.PipDescription;
PipSemiStableHash = info.PipSemiStableHash;
TimeoutDumpDirectory = info.TimeoutDumpDirectory;
ShouldReportFileAccesses = info.FileAccessManifest?.ReportFileAccesses == true;
ShouldReportFileAccesses = info.FileAccessManifest.ReportFileAccesses;
DetoursListener = info.DetoursEventListener;
UniqueName = $"Pip{info.FileAccessManifest?.PipId:X}.{Interlocked.Increment(ref m_uniqueNameCounter)}";
UniqueName = $"Pip{info.FileAccessManifest.PipId:X}.{Interlocked.Increment(ref m_uniqueNameCounter)}";
info.Timeout ??= s_defaultProcessTimeout;

Просмотреть файл

@ -489,33 +489,35 @@ namespace BuildXL.SandboxedProcessExecutor
}
}
foreach (var tmpEnvVar in BuildParameters.DisallowedTempVariables)
if (info.EnvironmentVariables != null)
{
if (info.EnvironmentVariables.ContainsKey(tmpEnvVar))
foreach (var tmpEnvVar in BuildParameters.DisallowedTempVariables)
{
string tempPath = info.EnvironmentVariables[tmpEnvVar];
var result = PrepareTempDirectory(tempPath);
if (info.EnvironmentVariables.ContainsKey(tmpEnvVar))
{
string tempPath = info.EnvironmentVariables[tmpEnvVar];
var result = PrepareTempDirectory(tempPath);
if (!result.Succeeded)
{
m_logger.LogError($"Failed to prepare temporary directory '{tempPath}': {result.Failure.DescribeIncludingInnerFailures()}");
return false;
}
}
}
string vmSharedTemp = info.EnvironmentVariables.TryGetValue(VmSpecialEnvironmentVariables.VmSharedTemp, null);
if (!string.IsNullOrEmpty(vmSharedTemp))
{
// Ensure that the directory exists, but do not clean if it already exists because the directory is shared by multiple pips.
var result = PrepareTempDirectory(vmSharedTemp, cleanDirectoryIfExists: false);
if (!result.Succeeded)
{
m_logger.LogError($"Failed to prepare temporary directory '{tempPath}': {result.Failure.DescribeIncludingInnerFailures()}");
m_logger.LogError($"Failed to prepare VM shared temporary directory '{vmSharedTemp}': {result.Failure.DescribeIncludingInnerFailures()}");
return false;
}
}
}
}
string vmSharedTemp = info.EnvironmentVariables.TryGetValue(VmSpecialEnvironmentVariables.VmSharedTemp, null);
if (!string.IsNullOrEmpty(vmSharedTemp))
{
// Ensure that the directory exists, but do not clean if it already exists because the directory is shared by multiple pips.
var result = PrepareTempDirectory(vmSharedTemp, cleanDirectoryIfExists: false);
if (!result.Succeeded)
{
m_logger.LogError($"Failed to prepare VM shared temporary directory '{vmSharedTemp}': {result.Failure.DescribeIncludingInnerFailures()}");
return false;
}
}
if (remoteData == null)
{
return true;
@ -610,7 +612,7 @@ namespace BuildXL.SandboxedProcessExecutor
result.LastMessageCount = process.GetLastMessageCount();
result.DetoursMaxHeapSize = process.GetDetoursMaxHeapSize();
result.MessageCountSemaphoreCreated = info.FileAccessManifest.MessageCountSemaphore != null;
result.MessageCountSemaphoreCreated = fam.MessageCountSemaphore != null;
return (ExitCode.Success, result);
}