Class: Sys::ProcTable

Inherits:
Object
  • Object
show all
Extended by:
FFI::Library
Defined in:
lib/darwin/sys/proctable.rb,
lib/sys/proctable/version.rb

Defined Under Namespace

Classes: Error, ProcBsdInfo, ProcTableStruct, ProcTaskAllInfo, ProcTaskInfo, ProcThreadInfo, ThreadInfoStruct

Constant Summary collapse

VERSION =

The version of the sys-proctable library

'1.1.4'.freeze

Class Method Summary collapse

Class Method Details

.fieldsObject

Returns an array of fields that each ProcTableStruct will contain. This may be useful if you want to know in advance what fields are available without having to perform at least one read of the process table.

Example:

Sys::ProcTable.fields.each{ |field|
   puts "Field: #{field}"
}


141
142
143
# File 'lib/darwin/sys/proctable.rb', line 141

def self.fields
  @fields
end

.ps(pid = nil) ⇒ Object

In block form, yields a ProcTableStruct for each process entry that you have rights to. This method returns an array of ProcTableStruct’s in non-block form.

If a pid is provided, then only a single ProcTableStruct is yielded or returned, or nil if no process information is found for that pid.

Example:

# Iterate over all processes
ProcTable.ps do |proc_info|
   p proc_info
end

# Print process table information for only pid 1001
p ProcTable.ps(1001)

Raises:

  • (TypeError)


162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
# File 'lib/darwin/sys/proctable.rb', line 162

def self.ps(pid = nil)
  raise TypeError unless pid.is_a?(Fixnum) if pid

  num = proc_listallpids(nil, 0)
  ptr = FFI::MemoryPointer.new(:pid_t, num)
  num = proc_listallpids(ptr, ptr.size)

  raise SystemCallError.new('proc_listallpids', FFI.errno) if num == 0

  pids  = ptr.get_array_of_int32(0, num).sort
  array = block_given? ? nil : []

  pids.each do |lpid|
    next unless pid == lpid if pid
    info = ProcTaskAllInfo.new

    nb = proc_pidinfo(lpid, PROC_PIDTASKALLINFO, 0, info, info.size)

    if nb <= 0
      if [Errno::EPERM::Errno, Errno::ESRCH::Errno].include?(FFI.errno)
        next # Either we don't have permission, or the pid no longer exists
      else
        raise SystemCallError.new('proc_pidinfo', FFI.errno)
      end
    end

    # Avoid potentially invalid data
    next if nb != info.size

    struct = ProcTableStruct.new

    # Pass by reference
    get_cmd_args_and_env(lpid, struct)
    get_thread_info(lpid, struct, info[:ptinfo])

    # Chop the leading xx_ from the FFI struct members for our ruby struct.
    info.members.each do |nested|
      info[nested].members.each do |member|
        temp = member.to_s.split('_')
        sproperty = temp.size > 1 ? temp[1..-1].join('_') : temp.first
        if info[nested][member].is_a?(FFI::StructLayout::CharArray)
          struct[sproperty.to_sym] = info[nested][member].to_s
        else
          struct[sproperty.to_sym] = info[nested][member]
        end
      end
    end

    struct.freeze

    if block_given?
      yield struct
    else
      array << struct
    end
  end

  return nil if array.nil?
  pid ? array.first : array
end