[Win32utils-devel] Simulating Process.getrlimit

Heesob Park phasis at gmail.com
Sat Jul 18 10:46:16 EDT 2009


Hi,

2009/7/18 Daniel Berger <djberg96 at gmail.com>:
> 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?
>
I guess the value 0 means no limit.
If you call QueryInformationJobObject after setting some specific
limit with SetInformationJobObject, you will get the same value.

> 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?
>
If you want the information of the current process only, you don't
need to call CreateJobObject and AssignProcessToJobObject, just call
QueryInformationJobObject with null job handle.
But SetInformationJobObject cannot be called with null job handle.

> Also, does the above approach seem reasonable in general? Any suggestions
> for other RLIMIT constants?
>
I have no idea.

Regards,

Park Heesob


More information about the win32utils-devel mailing list