public ProcessContainer(Process p, Job j) { _proc = p; _job = j; handle = CreateJobObject(IntPtr.Zero, null); var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = 0x2000 }; var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = info }; int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length); Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error())); } // Set the value to an unknown Result = InteractionResult.Unknown; }
public ChildProcessManager(ulong memoryLimit) { _handle = new SafeJobHandle(CreateJobObject(IntPtr.Zero, null)); var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = 0x00000100 }; var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = info, ProcessMemoryLimit = (UIntPtr)memoryLimit }; var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); var extendedInfoPtr = Marshal.AllocHGlobal(length); Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!SetInformationJobObject(_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new InvalidOperationException($"Unable to set information. Error: {Marshal.GetLastWin32Error()}"); } }
private static SafeFileHandle CreateJobHandle() { var handle = NativeMethods.CreateJobObject(IntPtr.Zero, null); if (handle == null) { throw new LastWin32ErrorException("Error creating job handle"); } var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION(); info.LimitFlags = 0x2000; var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION(); extendedInfo.BasicLimitInformation = info; int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); var extendedInfoPtr = Marshal.AllocHGlobal(length); try { Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!NativeMethods.SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new LastWin32ErrorException("Unable to set job information"); } return(handle); } finally { Marshal.FreeHGlobal(extendedInfoPtr); } }
public Job() { const uint JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE = 0x2000; const uint JOB_OBJECT_LIMIT_BREAKAWAY_OK = 0x800; _handle = CreateJobObject(IntPtr.Zero, null); var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE | JOB_OBJECT_LIMIT_BREAKAWAY_OK }; var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = info }; int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length); Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!SetInformationJobObject(_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error())); } }
public JOBOBJECT_EXTENDED_LIMIT_INFORMATION(JOBOBJECT_BASIC_LIMIT_INFORMATION BasicLimitInformation = default, IO_COUNTERS IoInfo = default, System.UIntPtr ProcessMemoryLimit = default, System.UIntPtr JobMemoryLimit = default, System.UIntPtr PeakProcessMemoryUsed = default, System.UIntPtr PeakJobMemoryUsed = default) { this.BasicLimitInformation = BasicLimitInformation; this.IoInfo = IoInfo; this.ProcessMemoryLimit = ProcessMemoryLimit; this.JobMemoryLimit = JobMemoryLimit; this.PeakProcessMemoryUsed = PeakProcessMemoryUsed; this.PeakJobMemoryUsed = PeakJobMemoryUsed; }
public static IntPtr Create() { /* * Windows will automatically close any open job handles when our process terminates. * This can be verified by using SysInternals' readHandle utility. When the job handle * is closed, the child processes will be killed. * * This feature requires Windows 8 or later. To support Windows 7 requires * registry settings to be added if you are using Visual Studio plus an * app.manifest change. */ if (!Environment.OSVersion.IsWindows8OrHigher()) { return(IntPtr.Zero); } // The job name is optional (and can be null) but it helps with diagnostics. // If it's not null, it has to be unique. Use SysInternals' Handle command-line // utility: handle -a ChildProcessTracker string jobName = "ChildProcessTracker" + Process.GetCurrentProcess().Id; IntPtr jobHandle = Win32.CreateJobObject(IntPtr.Zero, jobName); JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = JobObjectLimitEnum.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE }; // This is the key flag. When our process is killed, Windows will automatically // close the job handle, and when that happens, we want the child processes to // be killed, too. JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = info }; int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length); try { Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!Win32.SetInformationJobObject(jobHandle, JobObjectInfoTypeEnum.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } } finally { Marshal.FreeHGlobal(extendedInfoPtr); } return(jobHandle); }
static void AttachChildProcessToThisProcess(Process proc) { //Attach 'proc' process to this process, so that it's closed along with this process try { if (ghJob == IntPtr.Zero) { ghJob = CreateJobObject(IntPtr.Zero, ""); //It will be closed automatically when this process exits or is terminated if (ghJob == IntPtr.Zero) { throw new Win32Exception(); } } JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION(); info.LimitFlags = JOBOBJECTLIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; JOBOBJECT_EXTENDED_LIMIT_INFORMATION exInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION(); exInfo.BasicLimitInformation = info; int nLength = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); IntPtr exInfoPtr = Marshal.AllocHGlobal(nLength); try { Marshal.StructureToPtr(exInfo, exInfoPtr, false); if (!SetInformationJobObject(ghJob, JobObjectInfoType.ExtendedLimitInformation, exInfoPtr, (uint)nLength)) { throw new Win32Exception(); } //And attach the process if (!AssignProcessToJobObject(ghJob, proc.Handle)) { throw new Win32Exception(); } } finally { Marshal.FreeHGlobal(exInfoPtr); } } catch (Exception ex) { //Error gEventLog.logMessage(EventLogMsgType.ELM_TYP_Error, "Failed to assign miner job: " + ex.ToString()); OutputConsoleError("ERROR: Failed to assign miner job: " + ex.ToString()); } }
static ChildProcessTracker() { // This feature requires Windows 8 or later. To support Windows 7 requires // registry settings to be added if you are using Visual Studio plus an // app.manifest change. // https://stackoverflow.com/a/4232259/386091 // https://stackoverflow.com/a/9507862/386091 if (Environment.OSVersion.Version < new Version(6, 2)) { return; } // The job name is optional (and can be null) but it helps with diagnostics. // If it's not null, it has to be unique. Use SysInternals' Handle command-line // utility: handle -a ChildProcessTracker string jobName = "ChildProcessTracker" + Process.GetCurrentProcess().Id; s_jobHandle = CreateJobObject(IntPtr.Zero, jobName); var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION { // This is the key flag. When our process is killed, Windows will automatically // close the job handle, and when that happens, we want the child processes to // be killed, too. LimitFlags = JOBOBJECTLIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE }; var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = info }; int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length); try { Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!SetInformationJobObject(s_jobHandle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new Win32Exception(); } } finally { Marshal.FreeHGlobal(extendedInfoPtr); } }
static ProcessHelper() { job = CreateJobObject(IntPtr.Zero, null); JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION(); info.LimitFlags = 0x2000; JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION(); extendedInfo.BasicLimitInformation = info; int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length); Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); SetInformationJobObject(job, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length); }
public static void Start(Process process = null) { // this is here to make it so if the player crashes // the process it started is killed along with it if (!Started) { if (jobHandle == IntPtr.Zero) { jobHandle = CreateJobObject(IntPtr.Zero, null); if (jobHandle == IntPtr.Zero) { throw new JobObjectException("Could not create the Job Object."); } } JOBOBJECT_BASIC_LIMIT_INFORMATION jobobjectBasicLimitInformation = new JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = JOB_OBJECT_LIMIT.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE }; JOBOBJECT_EXTENDED_LIMIT_INFORMATION jobobjectExtendedLimitInformation = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = jobobjectBasicLimitInformation }; int jobobjectExtendedLimitInformationSize = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); IntPtr jobobjectExtendedLimitInformationPointer = Marshal.AllocHGlobal(jobobjectExtendedLimitInformationSize); Marshal.StructureToPtr(jobobjectExtendedLimitInformation, jobobjectExtendedLimitInformationPointer, false); bool result = SetInformationJobObject(jobHandle, JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation, jobobjectExtendedLimitInformationPointer, (uint)jobobjectExtendedLimitInformationSize); Marshal.FreeHGlobal(jobobjectExtendedLimitInformationPointer); if (process == null) { process = Process.GetCurrentProcess(); } if (!result || !AssignProcessToJobObject(jobHandle, process.Handle)) { throw new JobObjectException("Could not set the Job Object Information or assign the Process to the Job Object."); } Started = true; } }
public Job() { m_handle = CreateJobObject(null, null); JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION(); info.LimitFlags = 0x2000; JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION(); extendedInfo.BasicLimitInformation = info; int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length); Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!SetInformationJobObject(m_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error())); } }
/// <summary> /// Creates a new <see cref="ChildProcessManager"/>. /// </summary> public ChildProcessManager() { if (Common.IsPosixEnvironment) { // On non-Windows operating systems we just track associated processes m_childProcesses = new List <WeakReference <Process> >(); } else { // Let safe handle manage terminations on Windows GC.SuppressFinalize(this); // On Windows we add child processes to a job object such that when the job // is terminated, so are the child processes. Since safe handle ensures proper // closing of job handle, child processes will be terminated even if parent // process is abnormally terminated m_jobHandle = new SafeJobHandle(CreateJobObject(IntPtr.Zero, null)); JOBOBJECT_BASIC_LIMIT_INFORMATION info = new JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = 0x2000 }; JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = info }; int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length); Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!SetInformationJobObject(m_jobHandle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new InvalidOperationException($"Unable to set information for ChildProcessManager job. Error: {Marshal.GetLastWin32Error()}"); } } }
public JobObject() { handle = NativeMethods.CreateJobObject(IntPtr.Zero, null); var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = KillOnJobClose }; var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = info }; var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); var extendedInfoPtr = Marshal.AllocHGlobal(length); Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!NativeMethods.SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error())); } }
public Job() { handle = CreateJobObject(IntPtr.Zero, null); var extendedInfoPtr = IntPtr.Zero; var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = 0x2000 }; var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = info }; try { int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); extendedInfoPtr = Marshal.AllocHGlobal(length); Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!SetInformationJobObject(handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new Exception(string.Format("Unable to set information. Error: {0}", Marshal.GetLastWin32Error())); } } finally { if (extendedInfoPtr != IntPtr.Zero) { Marshal.FreeHGlobal(extendedInfoPtr); extendedInfoPtr = IntPtr.Zero; } } }
public ChildProcessManager() { _handle = new SafeJobHandle(CreateJobObject(IntPtr.Zero, null)); var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION { LimitFlags = 0x2000 }; var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = info }; var length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION)); var extendedInfoPtr = Marshal.AllocHGlobal(length); Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false); if (!SetInformationJobObject(_handle, JobObjectInfoType.ExtendedLimitInformation, extendedInfoPtr, (uint)length)) { throw new InvalidOperationException($"Unable to set information. Error: {Marshal.GetLastWin32Error()}"); } }
internal static extern bool SetInformationJobObject(SafeJobObjectHandle hJob, JobObjectInformationClass JobObjectInfoClass, [In] ref JOBOBJECT_BASIC_LIMIT_INFORMATION lpJobObjectInfo, int cbJobObjectInfoLength);
internal static extern bool QueryInformationJobObject(SafeJobObjectHandle hJob, JobObjectInformationClass JobObjectInfoClass, [Out] out JOBOBJECT_BASIC_LIMIT_INFORMATION lpJobObjectInfo, int cbJobObjectInfoLength, IntPtr lpReturnLength);