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
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
Hi,> I guess the value 0 means no limit.Ok, thanks.>> 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.I get an error on both XP and Vista if I pass a null filehandle. require ''windows/process'' require ''windows/error'' include Windows::Process include Windows::Error buf = 0.chr * 48 val = nil # Set the LimitFlag buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_TIME].pack(''L'') bool = QueryInformationJobObject( nil, JobObjectBasicLimitInformation, buf, buf.size, nil ) unless bool raise Error, get_last_error end [val, val] # Return an array of two values to comply with spec What have I done wrong? Thanks, Dan
Hi, 2009/7/21 Daniel Berger <djberg96 at gmail.com>:> Hi, > >> I guess the value 0 means no limit. > > Ok, thanks. > >>> 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. > > I get an error on both XP and Vista if I pass a null filehandle. > > require ''windows/process'' > require ''windows/error'' > include Windows::Process > include Windows::Error > > buf = 0.chr * 48 > val = nil > > # Set the LimitFlag > buf[16,4] = [JOB_OBJECT_LIMIT_PROCESS_TIME].pack(''L'') > > bool = QueryInformationJobObject( > ? nil, > ? JobObjectBasicLimitInformation, > ? buf, > ? buf.size, > ? nil > ) > > unless bool > ? raise Error, get_last_error > end > > [val, val] # Return an array of two values to comply with spec > > What have I done wrong? >Sorry for misleading. The null jobhandle works only if the current process is already a member of a predefined job. You must check it by calling IsProcessInJob function with null jobhandle. Regards, Park Heesob