Example #1
0
        /// <summary>
        /// Initializes a new instance of the Job class.
        /// </summary>
        public Job()
        {
            IntPtr ptr = IntPtr.Zero;

            // this.jobObjectHandle = NativeMethods.CreateJobObject(IntPtr.Zero, null);
            this.jobObjectHandle = new SafeFileHandle(ptr, true);
            if (this.jobObjectHandle.IsInvalid)
            {
                // Note that the parameterless Win32Exception constructor calls Marshal.GetLastWin32Error internally.
                // throw new Win32Exception();
            }

            // -
            // Set up this job object so that any processes assigned to it will
            // be terminated when it is closed (since this job object will be
            // closed automatically when the owning process exits, all assigned
            // processes will also be closed when the owning process exists).
            // -
            // Note that to set the JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag,
            // the call to SetInformationJobObject must be of JobObjectInfoClass
            // ExtendedLimitInformation, even though the flag is in the simpler
            // BasicLimitInformation structure contained in the former.
            // -
            NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION info = new NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
            int infoSize = Marshal.SizeOf(typeof(NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION));

            info.BasicLimitInformation.LimitFlags =
                NativeMethods.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

            IntPtr infoPtr = Marshal.AllocHGlobal(infoSize);

            try
            {
                Marshal.StructureToPtr(info, infoPtr, false);

                // if (!NativeMethods.SetInformationJobObject(
                //          this.jobObjectHandle,
                //          NativeMethods.JOBOBJECTINFOCLASS.ExtendedLimitInformation,
                //          infoPtr,
                //          (UInt32)infoSize))
                // {
                //     // Note that the parameterless Win32Exception constructor calls Marshal.GetLastWin32Error internally.
                //     throw new Win32Exception();
                // }
            }
            finally
            {
                Marshal.FreeHGlobal(infoPtr);
            }
        }
Example #2
0
        public JobObject()
        {
            handle = NativeMethods.CreateJobObject(IntPtr.Zero, null);

            var info = new NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION
            {
                LimitFlags = 0x2000
            };

            var extendedInfo = new NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION
            {
                BasicLimitInformation = info
            };

            SetInformationJobObject(handle, extendedInfo, NativeMethods.JobObjectInfoType.ExtendedLimitInformation);
        }
Example #3
0
        /// <summary>
        /// Initializes a new instance of the Job class.
        /// </summary>
        public Job()
        {
            this.jobObjectHandle = NativeMethods.CreateJobObject(IntPtr.Zero, null);
            if (this.jobObjectHandle.IsInvalid)
            {
                // Note that the parameterless Win32Exception constructor calls Marshal.GetLastWin32Error internally.
                throw new Win32Exception();
            }

            // -
            // Set up this job object so that any processes assigned to it will
            // be terminated when it is closed (since this job object will be
            // closed automatically when the owning process exits, all assigned
            // processes will also be closed when the owning process exists).
            // -
            // Note that to set the JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE flag,
            // the call to SetInformationJobObject must be of JobObjectInfoClass
            // ExtendedLimitInformation, even though the flag is in the simpler
            // BasicLimitInformation structure contained in the former.
            // -
            NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION info = new NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
            int infoSize = Marshal.SizeOf(typeof(NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION));

            info.BasicLimitInformation.LimitFlags =
                NativeMethods.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;

            IntPtr infoPtr = Marshal.AllocHGlobal(infoSize);

            try
            {
                Marshal.StructureToPtr(info, infoPtr, false);

                if (!NativeMethods.SetInformationJobObject(
                         this.jobObjectHandle,
                         NativeMethods.JOBOBJECTINFOCLASS.ExtendedLimitInformation,
                         infoPtr,
                         (UInt32)infoSize))
                {
                    // Note that the parameterless Win32Exception constructor calls Marshal.GetLastWin32Error internally.
                    throw new Win32Exception();
                }
            }
            finally
            {
                Marshal.FreeHGlobal(infoPtr);
            }
        }
Example #4
0
 public JobObject(string name, long memorySizeLimitInMb = 0L)
 {
     this.safeJobHandle = NativeMethods.CreateJobObject(IntPtr.Zero, name);
     if (this.safeJobHandle.IsInvalid)
     {
         int lastWin32Error = Marshal.GetLastWin32Error();
         ExTraceGlobals.UtilsTracer.TraceError <string, int>((long)name.GetHashCode(), "{0}: Failed to create Job object. Win32 ErrorCode: {1}", name, lastWin32Error);
         throw new Win32Exception(lastWin32Error, "Failed to create Job object. Error code is {0}.");
     }
     NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedLimits = default(NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION);
     extendedLimits.BasicLimitInformation.LimitFlags = 8192U;
     if (memorySizeLimitInMb > 0L)
     {
         extendedLimits.BasicLimitInformation.LimitFlags = (extendedLimits.BasicLimitInformation.LimitFlags | 256U);
         extendedLimits.ProcessMemoryLimit = new UIntPtr((uint)memorySizeLimitInMb * 1024U * 1024U);
     }
     this.safeJobHandle.SetExtendedLimits(extendedLimits);
 }
Example #5
0
        public VsInstance()
        {
            _jobObject = NativeMethods.CreateJobObject(IntPtr.Zero, null);
            if (_jobObject.IsInvalid)
            {
                throw new InvalidOperationException("Failed to create job object");
            }

            NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION objInfo = new NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
            objInfo.BasicLimitInformation.LimitFlags = NativeMethods.JOB_OBJECT_LIMIT.KILL_ON_JOB_CLOSE;
            if (!NativeMethods.SetInformationJobObject(
                    _jobObject,
                    NativeMethods.JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation,
                    ref objInfo,
                    Marshal.SizeOf(objInfo)
                    ))
            {
                _jobObject.Dispose();
                throw new InvalidOperationException("Failed to set job info");
            }
        }
Example #6
0
        /// <summary>
        /// Updates the extended limit.
        /// </summary>
        private void UpdateExtendedLimit()
        {
            NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedLimit = new NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION();
            NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION    basicLimit    = new NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION();

            basicLimit.LimitFlags = 0;

            if (this.killProcessesOnJobClose)
            {
                basicLimit.LimitFlags |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
            }

            if (this.dieOnUnhandledException)
            {
                basicLimit.LimitFlags |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_DIE_ON_UNHANDLED_EXCEPTION;
            }

            if (this.allowChildProcessesBreakaway)
            {
                basicLimit.LimitFlags |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_BREAKAWAY_OK;
            }

            if (this.alwaysBreakawayChildProcesses)
            {
                basicLimit.LimitFlags |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_SILENT_BREAKAWAY_OK;
            }

            if (this.activeProcessesLimit != 0)
            {
                basicLimit.LimitFlags        |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_ACTIVE_PROCESS;
                basicLimit.ActiveProcessLimit = this.activeProcessesLimit;
            }

            if (this.processMemoryLimit != 0)
            {
                basicLimit.LimitFlags           |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_PROCESS_MEMORY;
                extendedLimit.ProcessMemoryLimit = (IntPtr)this.processMemoryLimit;
            }

            if (this.jobMemoryLimit != 0)
            {
                basicLimit.LimitFlags       |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_JOB_MEMORY;
                extendedLimit.JobMemoryLimit = (IntPtr)this.jobMemoryLimit;
            }

            if (this.processUserTimeLimit != 0)
            {
                basicLimit.LimitFlags |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_PROCESS_TIME;
                basicLimit.PerProcessUserTimeLimit = this.processUserTimeLimit;
            }

            if (this.jobUserTimeLimit != 0)
            {
                if (this.jobUserTimeLimitChanged)
                {
                    basicLimit.LimitFlags         |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_JOB_TIME;
                    basicLimit.PerJobUserTimeLimit = this.jobUserTimeLimit;
                    this.jobUserTimeLimitChanged   = false;
                }
                else
                {
                    basicLimit.LimitFlags |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_PRESERVE_JOB_TIME;
                }
            }

            if (this.priorityClass != 0)
            {
                basicLimit.LimitFlags   |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_PRIORITY_CLASS;
                basicLimit.PriorityClass = this.priorityClass;
            }

            if (this.schedulingClass != 0)
            {
                basicLimit.LimitFlags     |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_SCHEDULING_CLASS;
                basicLimit.SchedulingClass = this.schedulingClass;
            }

            if (this.affinity != IntPtr.Zero)
            {
                basicLimit.LimitFlags |= NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION.JOB_OBJECT_LIMIT_AFFINITY;
                basicLimit.Affinity    = this.affinity;
            }

            extendedLimit.BasicLimitInformation = basicLimit;

            int    extendedLimitLength = Marshal.SizeOf(typeof(NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
            IntPtr extendedLimitPtr    = Marshal.AllocHGlobal(extendedLimitLength);

            try
            {
                Marshal.StructureToPtr(extendedLimit, extendedLimitPtr, false);

                bool success = NativeMethods.SetInformationJobObject(this.jobHandle, NativeMethods.JobObjectInfoClass.JobObjectExtendedLimitInformation, extendedLimitPtr, (uint)extendedLimitLength);

                if (success == false)
                {
                    int error = Marshal.GetLastWin32Error();
                    throw new Win32Exception(error, "SetInformationJobObject failed.");
                }
            }
            finally
            {
                Marshal.FreeHGlobal(extendedLimitPtr);
            }
        }
Example #7
0
        internal bool InitializeJob()
        {
            // Create a job object and add the process to it. We do this to ensure that we can kill the process and
            // all its children in one shot.  Simply killing the process does not kill its children.
            NativeMethods.SECURITY_ATTRIBUTES jobSecAttributes = new NativeMethods.SECURITY_ATTRIBUTES();
            jobSecAttributes.bInheritHandle = true;
            jobSecAttributes.lpSecurityDescriptor = IntPtr.Zero;
            jobSecAttributes.nLength = Marshal.SizeOf(typeof(NativeMethods.SECURITY_ATTRIBUTES));

            IntPtr pointer = NativeMethods.CreateJobObject(ref jobSecAttributes, this.jobName);
            int createJobObjectWin32Error = Marshal.GetLastWin32Error();

            this.SetHandle(pointer);

            if (this.IsInvalid)
            {
                var error = string.Format("In InitializeJob.JobHandle: Failed to SetInformation for job {0} because {1}", this.jobName, createJobObjectWin32Error);
                Debug.WriteLine(error);
            }
            else
            {
                // LimitFlags include JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
                // to terminate all processes associated with the job when the last job handle is closed
                NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION basicInfo = new NativeMethods.JOBOBJECT_BASIC_LIMIT_INFORMATION();

                NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION extendedInfo = new NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = basicInfo };
                extendedInfo.BasicLimitInformation.LimitFlags = NativeMethods.JOB_OBJECT_LIMIT.KILL_ON_JOB_CLOSE;

                int length = Marshal.SizeOf(typeof(NativeMethods.JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
                IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
                Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);

                bool result = NativeMethods.SetInformationJobObject(this, NativeMethods.JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation, ref extendedInfo, length);
                int setInformationJobObjectWin32Error = Marshal.GetLastWin32Error();
                if (!result)
                {
                    //this.logger.LogError("InitializeJob", "JobHandle : Failed to SetInformation for job '{0}' because '{1}'", this.jobName, setInformationJobObjectWin32Error);
                }
                else
                {
                    return true;
                }
            }

            return false;
        }