Esempio n. 1
0
        static JobObjectInfo()
        {
            // create a JobObject and determine what options are supported on this OS..
            SafeJobObjectHandle jobHandle = null;

            try
            {
                jobHandle = Interop.Kernel32.CreateJobObject(IntPtr.Zero, null);
                if (jobHandle.IsInvalid)
                {
                    return;
                }

                _jobsSupported = true;

                // notification limit
                // notification limit 2
                // net rate control
                // violation limit
                // violation limit 2
                // job object group info
                // cpu rate control
                // group information ex

                IntPtr memoryPtr = IntPtr.Zero;
                try
                {
                    int memorySize = 1024;
                    memoryPtr = Marshal.AllocHGlobal(memorySize);

                    // ask for specific structures to determine the level of support..
                    _jobsGroupSupported           = IsSupported(jobHandle, Interop.Kernel32.JobObjectInformationClass.GroupInformation, memoryPtr, memorySize);
                    _jobsGroupExSupported         = IsSupported(jobHandle, Interop.Kernel32.JobObjectInformationClass.GroupInformationEx, memoryPtr, memorySize);
                    _jobsLimitViolationSupported  = IsSupported(jobHandle, Interop.Kernel32.JobObjectInformationClass.LimitViolationInformation, memoryPtr, memorySize);
                    _jobsLimitViolation2Supported = IsSupported(jobHandle, Interop.Kernel32.JobObjectInformationClass.LimitViolationInformation2, memoryPtr, memorySize);
                }
                finally
                {
                    if (memoryPtr != IntPtr.Zero)
                    {
                        Marshal.FreeHGlobal(memoryPtr);
                    }
                }
            }
            finally
            {
                jobHandle?.Dispose();
            }
        }
Esempio n. 2
0
        private void Dispose(bool disposing)
        {
            // remove completion handler before disposing handle, this should prevent a possible race with
            // another job object recyclying the handle value..

            if ((_handle != null) && (!_handle.IsClosed) && (!_handle.IsInvalid) && (_completionPort != null))
            {
                _completionPort.SetCompletionAction(_handle.DangerousGetHandle(), null);
            }

            // hold the _idleTaskLock while cancelling the idle task AND disposing the JobObject handle, we need
            // to ensure that if another thread is calling into GetIdleTask that it sees this instance has having
            // been disposed..

            lock (_idleTaskLock)
            {
                _handle?.Dispose();
                CompleteIdleTask(true);
            }

            _completionPort?.Dispose();
        }
Esempio n. 3
0
        public unsafe IChildProcessStateHolder SpawnProcess(
            ref ChildProcessStartInfoInternal startInfo,
            string resolvedPath,
            SafeHandle stdIn,
            SafeHandle stdOut,
            SafeHandle stdErr)
        {
            var arguments            = startInfo.Arguments;
            var environmentVariables = startInfo.EnvironmentVariables;
            var workingDirectory     = startInfo.WorkingDirectory;
            var flags = startInfo.Flags;

            Debug.Assert(startInfo.CreateNewConsole || ConsolePal.HasConsoleWindow());

            var commandLine      = WindowsCommandLineUtil.MakeCommandLine(resolvedPath, arguments ?? Array.Empty <string>(), !flags.HasDisableArgumentQuoting());
            var environmentBlock = startInfo.UseCustomEnvironmentVariables ? WindowsEnvironmentBlockUtil.MakeEnvironmentBlock(environmentVariables.Span) : null;

            // Objects that need cleanup
            InputWriterOnlyPseudoConsole?pseudoConsole   = null;
            SafeJobObjectHandle?         jobObjectHandle = null;
            SafeProcessHandle?           processHandle   = null;
            SafeThreadHandle?            threadHandle    = null;

            try
            {
                pseudoConsole = startInfo.CreateNewConsole ? InputWriterOnlyPseudoConsole.Create() : null;
                if (pseudoConsole is not null && flags.HasUseCustomCodePage())
                {
                    ChangeCodePage(pseudoConsole, startInfo.CodePage, workingDirectory);
                }

                bool killOnClose = startInfo.AllowSignal && WindowsVersion.NeedsWorkaroundForWindows1809;
                jobObjectHandle = CreateJobObject(killOnClose, startInfo.DisableWindowsErrorReportingDialog);

                using var inheritableHandleStore = new InheritableHandleStore(3);
                var childStdIn = stdIn != null?inheritableHandleStore.Add(stdIn) : null;

                var childStdOut = stdOut != null?inheritableHandleStore.Add(stdOut) : null;

                var childStdErr = stdErr != null?inheritableHandleStore.Add(stdErr) : null;

                IntPtr jobObjectHandles = jobObjectHandle.DangerousGetHandle();

                Span <IntPtr> inheritableHandles = stackalloc IntPtr[inheritableHandleStore.Count];
                inheritableHandleStore.DangerousGetHandles(inheritableHandles);
                fixed(IntPtr *pInheritableHandles = inheritableHandles)
                {
                    using var attr = new ProcThreadAttributeList(3);
                    if (pseudoConsole is not null)
                    {
                        attr.UpdatePseudoConsole(pseudoConsole.Handle.DangerousGetHandle());
                    }
                    attr.UpdateHandleList(pInheritableHandles, inheritableHandles.Length);
                    attr.UpdateJobList(&jobObjectHandles, 1);

                    const int CreationFlags =
                        Kernel32.CREATE_UNICODE_ENVIRONMENT
                        | Kernel32.EXTENDED_STARTUPINFO_PRESENT;

                    int processId;

                    (processId, processHandle, threadHandle) = InvokeCreateProcess(
                        commandLine,
                        CreationFlags,
                        environmentBlock,
                        workingDirectory,
                        childStdIn,
                        childStdOut,
                        childStdErr,
                        attr);

                    return(new WindowsChildProcessState(processId, processHandle, jobObjectHandle, pseudoConsole, startInfo.AllowSignal));
                }
            }
            catch
            {
                if (processHandle is not null)
                {
                    Kernel32.TerminateProcess(processHandle, -1);
                    processHandle.Dispose();
                }
                pseudoConsole?.Dispose();
                jobObjectHandle?.Dispose();
                throw;
            }
            finally
            {
                threadHandle?.Dispose();
            }
        }