Exemple #1
0
        /// <summary>
        /// Creates a new AsyncStreamReader for the given stream.  The
        /// character encoding is set by encoding and the buffer size,
        /// in number of 16-bit characters, is set by bufferSize.
        /// </summary>
        public AsyncPipeReader(
            IAsyncFile file,
            StreamDataReceived callback,
            Encoding encoding,
            int bufferSize)
        {
            Contract.Requires(file != null);
            Contract.Requires(file.CanRead);
            Contract.Requires(file.Kind == FileKind.Pipe);
            Contract.Requires(encoding != null);
            Contract.Requires(bufferSize > 128);
            m_file                    = file;
            m_userCallBack            = callback;
            m_decoder                 = encoding.GetDecoder();
            m_pooledByteBufferWrapper = Pools.GetByteArray(bufferSize);
            m_byteBufferSize          = bufferSize;
            m_byteBufferPin           = GCHandle.Alloc(ByteBuffer, GCHandleType.Pinned);
            m_byteBufferPtr           = (byte *)m_byteBufferPin.AddrOfPinnedObject();

            var maxCharsPerBuffer = encoding.GetMaxCharCount(bufferSize);

            m_pooledCharBufferWrapper    = Pools.GetCharArray(maxCharsPerBuffer);
            m_pooledStringBuilderWrapper = Pools.GetStringBuilder();
            StringBuilderInstace.Clear();
            StringBuilderInstace.EnsureCapacity(maxCharsPerBuffer * 2);
        }
 /// <summary>
 /// Constructor.
 /// </summary>
 public StreamAsyncPipeReader(
     NamedPipeServerStream pipeStream,
     StreamDataReceived callback,
     Encoding encoding,
     int bufferSize)
 {
     m_pipeStream   = pipeStream;
     m_userCallBack = callback;
     m_reader       = new StreamReader(pipeStream, encoding, false, bufferSize);
 }
Exemple #3
0
        public DetouredProcess(
            int bufferSize,
            string commandLine,
            string workingDirectory,
            byte[] unicodeEnvironmentBlock,
            Encoding standardInputEncoding,
            Encoding standardErrorEncoding,
            StreamDataReceived errorDataReceived,
            Encoding standardOutputEncoding,
            StreamDataReceived outputDataReceived,
            Func <Task> processExitingAsync,
            Func <Task> processExited,
            TimeSpan?timeout,
            bool disableConHostSharing,
            LoggingContext loggingContext,
            string timeoutDumpDirectory,
            ContainerConfiguration containerConfiguration,
            bool setJobBreakawayOk,
            bool createJobObjectForCurrentProcess)
        {
            Contract.Requires(bufferSize >= 128);
            Contract.Requires(!string.IsNullOrEmpty(commandLine));
            Contract.Requires(standardInputEncoding != null);
            Contract.Requires(standardErrorEncoding != null);
            Contract.Requires(standardOutputEncoding != null);
            Contract.Requires(!timeout.HasValue || timeout.Value <= Process.MaxTimeout);

            m_bufferSize              = bufferSize;
            m_commandLine             = commandLine;
            m_workingDirectory        = workingDirectory;
            m_unicodeEnvironmentBlock = unicodeEnvironmentBlock;
            m_standardInputEncoding   = standardInputEncoding;
            m_standardErrorEncoding   = standardErrorEncoding;
            m_errorDataReceived       = errorDataReceived;
            m_standardOutputEncoding  = standardOutputEncoding;
            m_outputDataReceived      = outputDataReceived;
            m_processExitingAsync     = processExitingAsync;
            m_processExited           = processExited;
            m_timeout = timeout;
            m_disableConHostSharing            = disableConHostSharing;
            m_containerConfiguration           = containerConfiguration;
            m_setJobBreakawayOk                = setJobBreakawayOk;
            m_createJobObjectForCurrentProcess = createJobObjectForCurrentProcess;
            if (m_workingDirectory != null && m_workingDirectory.Length == 0)
            {
                m_workingDirectory = Directory.GetCurrentDirectory();
            }

            m_loggingContext       = loggingContext;
            m_timeoutDumpDirectory = timeoutDumpDirectory;
        }
Exemple #4
0
        /// <summary>
        /// Creates a pipe reader.
        /// </summary>
        public static IAsyncPipeReader CreateNonDefaultPipeReader(
            NamedPipeServerStream pipeStream,
            StreamDataReceived callback,
            Encoding encoding,
            int bufferSize)
        {
            if (GetKind() == Kind.Pipeline)
            {
#if NET_COREAPP_60
                return(new PipelineAsyncPipeReader(pipeStream, callback, encoding));
#endif
            }

            // Fall back to use StreamReader based one.
            return(new StreamAsyncPipeReader(pipeStream, callback, encoding, bufferSize));
        }
Exemple #5
0
        public void Event_StreamDataReceived(BoltConnection connection, UdpStreamData streamData)
        {
            INetworkInterfaceConnection interfaceConnection = FindInterfaceConnection(connection);

            if (interfaceConnection == null)
            {
                Log.Error($"[PhotonNetworkInterface] Received stream data from an unknown connection: {connection}.");
                return;
            }

            IStreamChannel streamChannel = FindStreamChannel(streamData.Channel);

            if (streamChannel == null)
            {
                Log.Error($"[PhotonNetworkInterface] Received stream data from an unknown channel '{streamData.Channel}'.");
                return;
            }

            Log.Info(LogChannel, "[PhotonNetworkInterface] Incoming stream data received: (length)" + streamData.Data.Length);

            StreamDataReceived?.Invoke(streamData.Data, streamChannel, interfaceConnection);
        }
Exemple #6
0
        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));
        }
        public void Start()
        {
            Contract.Assume(!m_processStarted);

            Encoding        reportEncoding  = Encoding.Unicode;
            SafeFileHandle  childHandle     = null;
            DetouredProcess detouredProcess = m_detouredProcess;

            bool useNonDefaultPipeReader = PipeReaderFactory.GetKind() != PipeReaderFactory.Kind.Default;

            using (m_reportReaderSemaphore.AcquireSemaphore())
            {
                NamedPipeServerStream pipeStream   = null;
                SafeFileHandle        reportHandle = null;

                try
                {
                    if (useNonDefaultPipeReader)
                    {
                        pipeStream = Pipes.CreateNamedPipeServerStream(
                            PipeDirection.In,
                            PipeOptions.Asynchronous,
                            PipeOptions.None,
                            out childHandle);
                    }
                    else
                    {
                        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(m_loggingContext, 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();
                }
                catch (AccessViolationException)
                {
                    int ramPercent = 0, availableRamMb = 0, availablePageFileMb = 0, totalPageFileMb = 0;

                    MEMORYSTATUSEX memoryStatusEx = new MEMORYSTATUSEX();
                    if (GlobalMemoryStatusEx(memoryStatusEx))
                    {
                        ramPercent          = (int)memoryStatusEx.dwMemoryLoad;
                        availableRamMb      = new FileSize(memoryStatusEx.ullAvailPhys).MB;
                        availablePageFileMb = new FileSize(memoryStatusEx.ullAvailPageFile).MB;
                        totalPageFileMb     = new FileSize(memoryStatusEx.ullTotalPageFile).MB;
                    }

                    string memUsage = $"RamPercent: {ramPercent}, AvailableRamMb: {availableRamMb}, AvailablePageFileMb: {availablePageFileMb}, TotalPageFileMb: {totalPageFileMb}";
                    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)
                    {
                        childHandle.Dispose();
                    }
                }

                StreamDataReceived reportLineReceivedCallback = m_reports == null ? null : ReportLineReceived;

                if (useNonDefaultPipeReader)
                {
                    m_reportReader = PipeReaderFactory.CreateNonDefaultPipeReader(
                        pipeStream,
                        message => reportLineReceivedCallback(message),
                        reportEncoding,
                        m_bufferSize);
                }
                else
                {
                    var reportFile = AsyncFileFactory.CreateAsyncFile(
                        reportHandle,
                        FileDesiredAccess.GenericRead,
                        ownsHandle: true,
                        kind: FileKind.Pipe);
                    m_reportReader = new AsyncPipeReader(
                        reportFile,
                        reportLineReceivedCallback,
                        reportEncoding,
                        m_bufferSize,
                        numOfRetriesOnCancel: m_numRetriesPipeReadOnCancel,
                        debugPipeReporter: new AsyncPipeReader.DebugReporter(errorMsg => DebugPipeConnection($"ReportReader: {errorMsg}")));
                }

                m_reportReader.BeginReadLine();
            }

            // don't wait, we want feeding in of standard input to happen asynchronously
            Analysis.IgnoreResult(FeedStandardInputAsync(detouredProcess, m_standardInputReader, m_standardInputTcs));
        }