[Win32utils-devel] Simulating Process.getrlimit

Daniel Berger djberg96 at gmail.com
Sat Jul 18 08:32:09 EDT 2009


Hi,

I've added several job functions and constants to the windows-pr library (in
CVS). I was hoping that with the job functions we could provide an analogue
for Process.getrlimit and Process.setrlimit.

My initial stab at Process.getrlimit doesn't quite work. I always get 0 for
the result:

module Process
   undef_method :getrlimit

   unless defined? RLIMIT_CPU
      RLIMIT_CPU    = 0 # PerProcessUserTimeLimit
      RLIMIT_FSIZE  = 1 # Hard coded at 4TB - 64K (assumes NTFS)
      RLIMIT_AS     = 5 # ProcessMemoryLimit
      RLIMIT_RSS    = 5 # ProcessMemoryLimit
      RLIMIT_VMEM   = 5 # ProcessMemoryLimit
   end

   def getrlimit(resource)
      # Strictly for API compatibility (actually 4 GB on FAT32)
      if resource == RLIMIT_FSIZE
         return ((1024**4) * 4) - (1024 * 64)
      end

      job_name = 'ruby_' + Time.now.to_s

      # Create a job object and add the current process to it
      handle = CreateJobObject(nil, job_name)

      if handle == 0
         raise Error, get_last_error
      end

      begin
         unless AssignProcessToJobObject(handle, GetCurrentProcess())
            raise Error, get_last_error
         end

         buf = 0.chr * 112 # sizeof(struct
JOBJECT_EXTENDED_LIMIT_INFORMATION)
         val = nil         # value returned at end of method

         case resource
         when RLIMIT_CPU
            buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_TIME].pack('L')
         when RLIMIT_AS, RLIMIT_VMEM, RLIMIT_RSS
            buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_MEMORY].pack('L')
         end

         bool = QueryInformationJobObject(
            handle,
            JobObjectExtendedLimitInformation,
            buf,
            buf.size,
            nil
         )

         unless bool
            raise Error, get_last_error
         end

         case resource
         when Process::RLIMIT_CPU
            val = buf[0,8].unpack('Q').first
         when RLIMIT_AS, RLIMIT_VMEM, RLIMIT_RSS
            val = buf[96,4].unpack('L').first
         end
      ensure
         CloseHandle(handle)
      end

      [val, val] # Return an array of two values to comply with spec
   end
end

What am I doing wrong there?

The other problem I noticed is that you can't call Process.getrlimit more
than once per process, presumably because I don't call TerminateJobObject.
But if I call that it kills the process. I don't see a way around that. I
didn't see a way to remove a process from a job object first. Is there a
way?

Also, does the above approach seem reasonable in general? Any suggestions
for other RLIMIT constants?

Regards,

Dan



More information about the win32utils-devel mailing list