Method: Process.getrlimit

Defined in:
lib/win32/process.rb

.getrlimit(resource) ⇒ Object

Gets the resource limit of the current process. Only a limited number of flags are supported.

Process::RLIMIT_CPU Process::RLIMIT_FSIZE Process::RLIMIT_AS Process::RLIMIT_RSS Process::RLIMIT_VMEM

The Process:RLIMIT_AS, Process::RLIMIT_RSS and Process::VMEM constants all refer to the Process memory limit. The Process::RLIMIT_CPU constant refers to the per process user time limit. The Process::RLIMIT_FSIZE constant is hard coded to the maximum file size on an NTFS filesystem, approximately 4TB (or 4GB if not NTFS).

While a two element array is returned in order to comply with the spec, there is no separate hard and soft limit. The values will always be the same.

If [0,0] is returned then it means no limit has been set.

Example:

Process.getrlimit(Process::RLIMIT_VMEM) # => [0, 0]

– NOTE: Both the getrlimit and setrlimit method use an at_exit handler to close a job handle. This is necessary because simply calling it at the end of the block, while marking it for closure, would also make it unavailable within the same process again since it would no longer be associated with the job. In other words, trying to call it more than once within the same program would fail.



247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
# File 'lib/win32/process.rb', line 247

def getrlimit(resource)
  if resource == RLIMIT_FSIZE
    if volume_type == "NTFS"
      return ((1024**4) * 4) - (1024 * 64) # ~ 4TB
    else
      return (1024**3) * 4 # 4 GB
    end
  end

  handle = nil
  in_job = Process.job?

  # Put the current process in a job if it's not already in one
  if in_job && defined?(@win32_process_job_name)
    handle = OpenJobObjectA(JOB_OBJECT_QUERY, 1, @win32_process_job_name)
    raise SystemCallError, FFI.errno, "OpenJobObject" if handle == 0
  else
    @win32_process_job_name = "ruby_" + Process.pid.to_s
    handle = CreateJobObjectA(nil, @win32_process_job_name)
    raise SystemCallError, FFI.errno, "CreateJobObject" if handle == 0
  end

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

    ptr = JOBJECT_EXTENDED_LIMIT_INFORMATION.new
    val = nil

    # Set the LimitFlags member of the struct
    case resource
      when RLIMIT_CPU
        ptr[:BasicLimitInformation][:LimitFlags] = JOB_OBJECT_LIMIT_PROCESS_TIME
      when RLIMIT_AS, RLIMIT_VMEM, RLIMIT_RSS
        ptr[:BasicLimitInformation][:LimitFlags] = JOB_OBJECT_LIMIT_PROCESS_MEMORY
      else
        raise ArgumentError, "unsupported resource type: '#{resource}'"
    end

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

    unless bool
      raise SystemCallError, FFI.errno, "QueryInformationJobObject"
    end

    case resource
      when Process::RLIMIT_CPU
        val = ptr[:BasicLimitInformation][:PerProcessUserTimeLimit][:QuadPart]
      when RLIMIT_AS, RLIMIT_VMEM, RLIMIT_RSS
        val = ptr[:ProcessMemoryLimit]
    end

  ensure
    at_exit { CloseHandle(handle) if handle }
  end

  [val, val]
end