public ProcessTreeContext(Guid payloadGuid, SafeHandle reportPipe, ArraySegment <byte> payload, string dllNameX64, string dllNameX86, LoggingContext loggingContext) { // We cannot create this object in a wow64 process Contract.Assume( !ProcessUtilities.IsWow64Process(), "ProcessTreeContext:ctor - Cannot run injection server in a wow64 32 bit process"); SafeFileHandle childHandle = null; m_loggingContext = loggingContext; // This object will be the server for the tree. CreateSourceFile the pipe server. try { SafeFileHandle injectorHandle; // Create a pipe for the requests Pipes.CreateInheritablePipe(Pipes.PipeInheritance.InheritWrite, Pipes.PipeFlags.ReadSideAsync, out injectorHandle, out childHandle); // Create the injector. This will duplicate the handles. Injector = ProcessUtilities.CreateProcessInjector(payloadGuid, childHandle, reportPipe, dllNameX86, dllNameX64, payload); // Create the request reader. We don't start listening until requested var injectionRequestFile = AsyncFileFactory.CreateAsyncFile( injectorHandle, FileDesiredAccess.GenericRead, ownsHandle: true, kind: FileKind.Pipe); m_injectionRequestReader = new AsyncPipeReader(injectionRequestFile, InjectCallback, Encoding.Unicode, BufferSize); } catch (Exception exception) { if (Injector != null) { Injector.Dispose(); Injector = null; } if (m_injectionRequestReader != null) { m_injectionRequestReader.Dispose(); m_injectionRequestReader = null; } throw new BuildXLException("Process Tree Context injector could not be created", exception); } finally { // Release memory. Since the child handle is duplicated, it can be released if (childHandle != null && !childHandle.IsInvalid) { childHandle.Dispose(); } } }
private async Task WaitUntilReportEof(bool cancel) { using (await m_reportReaderSemaphore.AcquireAsync()) { if (m_reportReader != null) { if (!cancel) { await m_reportReader.WaitUntilEofAsync(); } m_reportReader.Dispose(); m_reportReader = null; } } }
public void Dispose() { // We dispose the injector first since it must have a write-handle to the pipe (to give to children). // EOF can't be reached until all writable handles are closed. // Requests after injector-dispose turn into no-ops (synchronized with a lock), and so the caller should take care to call Stop() // only after all processes have exited. if (Injector != null) { PrepareToStop(); } if (m_injectionRequestReader != null) { m_injectionRequestReader.Dispose(); m_injectionRequestReader = null; } }
public void Start() { Contract.Assume(!m_processStarted); Encoding reportEncoding = Encoding.Unicode; SafeFileHandle childHandle = null; DetouredProcess detouredProcess = m_detouredProcess; using (m_reportReaderSemaphore.AcquireSemaphore()) { SafeFileHandle reportHandle; try { Pipes.CreateInheritablePipe( Pipes.PipeInheritance.InheritWrite, Pipes.PipeFlags.ReadSideAsync, readHandle: out reportHandle, writeHandle: out childHandle); var setup = new FileAccessSetup { ReportPath = "#" + childHandle.DangerousGetHandle().ToInt64(), DllNameX64 = s_binaryPaths.DllNameX64, DllNameX86 = s_binaryPaths.DllNameX86, }; bool debugFlagsMatch = true; ArraySegment <byte> manifestBytes = new ArraySegment <byte>(); if (m_fileAccessManifest != null) { manifestBytes = m_fileAccessManifest.GetPayloadBytes(setup, FileAccessManifestStream, m_timeoutMins, ref debugFlagsMatch); } if (!debugFlagsMatch) { throw new BuildXLException("Mismatching build type for BuildXL and DetoursServices.dll."); } m_standardInputTcs = TaskSourceSlim.Create <bool>(); detouredProcess.Start( s_payloadGuid, manifestBytes, childHandle, s_binaryPaths.DllNameX64, s_binaryPaths.DllNameX86); // At this point, we believe calling 'kill' will result in an eventual callback for job teardown. // This knowledge is significant for ensuring correct cleanup if we did vs. did not start a process; // if started, we expect teardown to happen eventually and clean everything up. m_processStarted = true; ProcessId = detouredProcess.GetProcessId(); m_processIdListener?.Invoke(ProcessId); } finally { // release memory m_fileAccessManifest = null; // Note that in the success path, childHandle should already be closed (by Start). if (childHandle != null && !childHandle.IsInvalid) { childHandle.Dispose(); } } var reportFile = AsyncFileFactory.CreateAsyncFile( reportHandle, FileDesiredAccess.GenericRead, ownsHandle: true, kind: FileKind.Pipe); StreamDataReceived reportLineReceivedCallback = m_reports == null ? (StreamDataReceived)null : ReportLineReceived; m_reportReader = new AsyncPipeReader(reportFile, reportLineReceivedCallback, reportEncoding, m_bufferSize); m_reportReader.BeginReadLine(); } // don't wait, we want feeding in of standard input to happen asynchronously Analysis.IgnoreResult(FeedStandardInputAsync(detouredProcess, m_standardInputReader, m_standardInputTcs)); }