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