void AssignProcessToJobObject() { var securityAttributes = new WinInterop.SecurityAttributes(); securityAttributes.nLength = Marshal.SizeOf(securityAttributes); hJob = CheckResult(WinJobs.NativeMethods.CreateJobObject(securityAttributes, "procgov-" + Guid.NewGuid())); // create completion port hIOCP = CheckResult(WinJobs.NativeMethods.CreateIoCompletionPort(WinHandles.NativeMethods.INVALID_HANDLE_VALUE, IntPtr.Zero, IntPtr.Zero, 1)); var assocInfo = new WinJobs.JOBOBJECT_ASSOCIATE_COMPLETION_PORT { CompletionKey = IntPtr.Zero, CompletionPort = hIOCP }; uint size = (uint)Marshal.SizeOf(assocInfo); CheckResult(WinJobs.NativeMethods.SetInformationJobObject(hJob, WinJobs.JOBOBJECTINFOCLASS.AssociateCompletionPortInformation, ref assocInfo, size)); // start listening thread listener = new Thread(CompletionPortListener); listener.Start(hIOCP); WinJobs.JobInformationLimitFlags flags = WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_BREAKAWAY_OK | WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK; if (maxProcessMemory > 0) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_PROCESS_MEMORY; } if (cpuAffinityMask != 0) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_AFFINITY; } long systemAffinity, processAffinity; CheckResult(WinProcesses.NativeMethods.GetProcessAffinityMask(hProcess, out processAffinity, out systemAffinity)); // configure constraints var limitInfo = new WinJobs.JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = new WinJobs.JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = flags, Affinity = systemAffinity & cpuAffinityMask }, ProcessMemoryLimit = (UIntPtr)maxProcessMemory }; size = (uint)Marshal.SizeOf(limitInfo); CheckResult(WinJobs.NativeMethods.SetInformationJobObject(hJob, WinJobs.JOBOBJECTINFOCLASS.ExtendedLimitInformation, ref limitInfo, size)); // assign a process to a job to apply constraints CheckResult(WinJobs.NativeMethods.AssignProcessToJobObject(hJob, hProcess.DangerousGetHandle())); }
void AssignProcessToJobObject() { var securityAttributes = new WinInterop.SecurityAttributes(); securityAttributes.nLength = Marshal.SizeOf(securityAttributes); hJob = CheckResult(WinJobs.NativeMethods.CreateJobObject(securityAttributes, "procgov-" + Guid.NewGuid())); // create completion port hIOCP = CheckResult(WinJobs.NativeMethods.CreateIoCompletionPort(WinHandles.NativeMethods.INVALID_HANDLE_VALUE, IntPtr.Zero, IntPtr.Zero, 1)); var assocInfo = new WinJobs.JOBOBJECT_ASSOCIATE_COMPLETION_PORT { CompletionKey = IntPtr.Zero, CompletionPort = hIOCP }; uint size = (uint)Marshal.SizeOf(assocInfo); CheckResult(WinJobs.NativeMethods.SetInformationJobObject(hJob, WinJobs.JOBOBJECTINFOCLASS.AssociateCompletionPortInformation, ref assocInfo, size)); WinJobs.JobInformationLimitFlags flags = 0; if (!propagateOnChildProcesses) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK; } if (maxProcessMemory > 0) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_PROCESS_MEMORY; } if (cpuAffinityMask != 0) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_AFFINITY; } if (processUserTimeLimitInMilliseconds > 0) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_PROCESS_TIME; } if (jobUserTimeLimitInMilliseconds > 0) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_JOB_TIME; } long systemAffinity, processAffinity; CheckResult(WinProcesses.NativeMethods.GetProcessAffinityMask(hProcess, out processAffinity, out systemAffinity)); // configure constraints var limitInfo = new WinJobs.JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = new WinJobs.JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = flags, Affinity = systemAffinity & cpuAffinityMask, PerProcessUserTimeLimit = 10_000 * processUserTimeLimitInMilliseconds, // in 100ns PerJobUserTimeLimit = 10_000 * jobUserTimeLimitInMilliseconds // in 100ns },
void AssignProcessToJobObject() { var securityAttributes = new WinInterop.SecurityAttributes(); securityAttributes.nLength = Marshal.SizeOf(securityAttributes); hJob = CheckResult(WinJobs.NativeMethods.CreateJobObject(securityAttributes, "procgov-" + Guid.NewGuid())); // create completion port hIOCP = CheckResult( WinJobs.NativeMethods.CreateIoCompletionPort(WinHandles.NativeMethods.INVALID_HANDLE_VALUE, IntPtr.Zero, IntPtr.Zero, 1)); var assocInfo = new WinJobs.JOBOBJECT_ASSOCIATE_COMPLETION_PORT { CompletionKey = IntPtr.Zero, CompletionPort = hIOCP }; uint size = (uint)Marshal.SizeOf(assocInfo); CheckResult(WinJobs.NativeMethods.SetInformationJobObject(hJob, WinJobs.JOBOBJECTINFOCLASS.JobObjectAssociateCompletionPortInformation, ref assocInfo, size)); WinJobs.JobInformationLimitFlags flags = 0; if (!PropagateOnChildProcesses) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK; } if (MaxProcessMemory > 0) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_PROCESS_MEMORY; } if (MaxWorkingSetSize > 0) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_WORKINGSET; } if (ProcessUserTimeLimitInMilliseconds > 0) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_PROCESS_TIME; } if (JobUserTimeLimitInMilliseconds > 0) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_JOB_TIME; } // only if NUMA node is not provided we will set the CPU affinity, // otherwise we will set the affinity on a selected NUMA node if (CpuAffinityMask != 0 && numaNode == 0xffff) { flags |= WinJobs.JobInformationLimitFlags.JOB_OBJECT_LIMIT_AFFINITY; } CheckResult(WinProcesses.NativeMethods.GetProcessAffinityMask(hProcess, out _, out var systemAffinityMask)); if (flags != 0) { // configure basic constraints var limitInfo = new WinJobs.JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = new WinJobs.JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = flags, Affinity = systemAffinityMask & CpuAffinityMask, PerProcessUserTimeLimit = 10_000 * ProcessUserTimeLimitInMilliseconds, // in 100ns PerJobUserTimeLimit = 10_000 * JobUserTimeLimitInMilliseconds, // in 100ns MaximumWorkingSetSize = (UIntPtr)MaxWorkingSetSize, },
public static extern bool SetInformationJobObject(IntPtr hJob, JOBOBJECTINFOCLASS JobObjectInfoClass, ref JOBOBJECT_ASSOCIATE_COMPLETION_PORT lpJobObjectInfo, uint cbJobObjectInfoLength);