sys-proctable 1.2.6 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +0 -0
- data/{CHANGES.rdoc → CHANGES.md} +69 -49
- data/Gemfile +2 -0
- data/{MANIFEST.rdoc → MANIFEST.md} +9 -1
- data/README.md +9 -3
- data/Rakefile +10 -7
- data/certs/djberg96_pub.pem +26 -0
- data/lib/bsd/sys/dragonfly/sys/proctable/constants.rb +11 -0
- data/lib/bsd/sys/dragonfly/sys/proctable/functions.rb +14 -0
- data/lib/bsd/sys/dragonfly/sys/proctable/structs.rb +298 -0
- data/lib/bsd/sys/dragonfly/sys/proctable.rb +175 -0
- data/lib/bsd/sys/freebsd/sys/proctable/constants.rb +0 -0
- data/lib/bsd/sys/freebsd/sys/proctable/functions.rb +0 -0
- data/lib/bsd/sys/freebsd/sys/proctable/structs.rb +0 -0
- data/lib/{freebsd → bsd/sys/freebsd}/sys/proctable.rb +1 -1
- data/lib/bsd/sys/proctable.rb +8 -0
- data/lib/darwin/sys/proctable.rb +53 -20
- data/lib/linux/sys/proctable/cgroup_entry.rb +4 -2
- data/lib/linux/sys/proctable/smaps.rb +29 -17
- data/lib/linux/sys/proctable.rb +41 -35
- data/lib/sunos/sys/proctable.rb +2 -2
- data/lib/sys/proctable/version.rb +1 -1
- data/lib/sys/proctable.rb +2 -2
- data/lib/sys/top.rb +7 -2
- data/lib/windows/sys/proctable.rb +36 -32
- data/spec/spec_helper.rb +15 -0
- data/spec/sys_proctable_aix_spec.rb +74 -76
- data/spec/sys_proctable_all_spec.rb +45 -45
- data/spec/sys_proctable_bsd_spec.rb +244 -0
- data/spec/sys_proctable_darwin_spec.rb +85 -58
- data/spec/sys_proctable_linux_spec.rb +196 -195
- data/spec/sys_proctable_sunos_spec.rb +190 -192
- data/spec/sys_proctable_windows_spec.rb +153 -153
- data/spec/sys_top_spec.rb +20 -21
- data/sys-proctable.gemspec +16 -24
- data.tar.gz.sig +0 -0
- metadata +78 -18
- metadata.gz.sig +0 -0
- data/spec/sys_proctable_freebsd_spec.rb +0 -210
@@ -0,0 +1,298 @@
|
|
1
|
+
require 'ffi'
|
2
|
+
require_relative 'constants'
|
3
|
+
|
4
|
+
module Sys
|
5
|
+
module ProcTableStructs
|
6
|
+
extend FFI::Library
|
7
|
+
|
8
|
+
class Timeval < FFI::Struct
|
9
|
+
layout(:tv_sec, :time_t, :tv_usec, :suseconds_t)
|
10
|
+
end
|
11
|
+
|
12
|
+
class RTPrio < FFI::Struct
|
13
|
+
layout(:type, :ushort, :prio, :ushort)
|
14
|
+
end
|
15
|
+
|
16
|
+
class Rusage < FFI::Struct
|
17
|
+
layout(
|
18
|
+
:ru_utime, Timeval,
|
19
|
+
:ru_stime, Timeval,
|
20
|
+
:ru_maxrss, :long,
|
21
|
+
:ru_ixrss, :long,
|
22
|
+
:ru_idrss, :long,
|
23
|
+
:ru_isrss, :long,
|
24
|
+
:ru_minflt, :long,
|
25
|
+
:ru_majflt, :long,
|
26
|
+
:ru_nswap, :long,
|
27
|
+
:ru_inblock, :long,
|
28
|
+
:ru_oublock, :long,
|
29
|
+
:ru_msgsnd, :long,
|
30
|
+
:ru_msgrcv, :long,
|
31
|
+
:ru_nsignals, :long,
|
32
|
+
:ru_nvcsw, :long,
|
33
|
+
:ru_nivcsw, :long
|
34
|
+
)
|
35
|
+
|
36
|
+
def utime
|
37
|
+
Time.at(self[:ru_utime][:tv_sec])
|
38
|
+
end
|
39
|
+
|
40
|
+
def stime
|
41
|
+
Time.at(self[:ru_stime][:tv_sec])
|
42
|
+
end
|
43
|
+
|
44
|
+
def maxrss
|
45
|
+
self[:ru_maxrss]
|
46
|
+
end
|
47
|
+
|
48
|
+
def ixrss
|
49
|
+
self[:ru_ixrss]
|
50
|
+
end
|
51
|
+
|
52
|
+
def idrss
|
53
|
+
self[:ru_idrss]
|
54
|
+
end
|
55
|
+
|
56
|
+
def isrss
|
57
|
+
self[:ru_isrss]
|
58
|
+
end
|
59
|
+
|
60
|
+
def minflt
|
61
|
+
self[:ru_minflt]
|
62
|
+
end
|
63
|
+
|
64
|
+
def majflt
|
65
|
+
self[:ru_majflt]
|
66
|
+
end
|
67
|
+
|
68
|
+
def nswap
|
69
|
+
self[:ru_nswap]
|
70
|
+
end
|
71
|
+
|
72
|
+
def inblock
|
73
|
+
self[:ru_inblock]
|
74
|
+
end
|
75
|
+
|
76
|
+
def oublock
|
77
|
+
self[:ru_oublock]
|
78
|
+
end
|
79
|
+
|
80
|
+
def msgsnd
|
81
|
+
self[:ru_msgsnd]
|
82
|
+
end
|
83
|
+
|
84
|
+
def msgrcv
|
85
|
+
self[:ru_msgrcv]
|
86
|
+
end
|
87
|
+
|
88
|
+
def nsignals
|
89
|
+
self[:ru_nsignals]
|
90
|
+
end
|
91
|
+
|
92
|
+
def nvcsw
|
93
|
+
self[:ru_nivcsw]
|
94
|
+
end
|
95
|
+
|
96
|
+
def nivcsw
|
97
|
+
self[:ru_nivcsw]
|
98
|
+
end
|
99
|
+
end
|
100
|
+
|
101
|
+
enum :lwpstat, [:LSRUN, 1, :LSSTOP, :LSSLEEP]
|
102
|
+
enum :procstat, [:SIDL, 1, :SACTIVE, :SSTOP, :SZOMB, :SCORE]
|
103
|
+
|
104
|
+
class Sigset < FFI::Struct
|
105
|
+
layout(:__bits, [:uint, 4])
|
106
|
+
|
107
|
+
def bits
|
108
|
+
self[:__bits].to_a
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
class KInfoLWP < FFI::Struct
|
113
|
+
include Sys::ProcTableConstants
|
114
|
+
|
115
|
+
layout(
|
116
|
+
:kl_pid, :pid_t,
|
117
|
+
:kl_tid, :lwpid_t,
|
118
|
+
:kl_flags, :int,
|
119
|
+
:kl_stat, :lwpstat,
|
120
|
+
:kl_lock, :int,
|
121
|
+
:kl_tdflags, :int,
|
122
|
+
:kl_mpcount, :int,
|
123
|
+
:kl_prio, :int,
|
124
|
+
:kl_tdprio, :int,
|
125
|
+
:kl_rtprio, RTPrio,
|
126
|
+
:kl_uticks, :uint64_t,
|
127
|
+
:kl_sticks, :uint64_t,
|
128
|
+
:kl_iticks, :uint64_t,
|
129
|
+
:kl_cpticks, :uint64_t,
|
130
|
+
:kl_pctcpu, :uint,
|
131
|
+
:kl_slptime, :uint,
|
132
|
+
:kl_origcpu, :int,
|
133
|
+
:kl_estcpu, :int,
|
134
|
+
:kl_cpuid, :int,
|
135
|
+
:kl_ru, Rusage,
|
136
|
+
:kl_siglist, Sigset,
|
137
|
+
:kl_sigmask, Sigset,
|
138
|
+
:kl_wchan, :uintptr_t,
|
139
|
+
:kl_wmesg, [:char, WMESGLEN+1],
|
140
|
+
:kl_comm, [:char, MAXCOMLEN+1]
|
141
|
+
)
|
142
|
+
|
143
|
+
def pid
|
144
|
+
self[:kl_pid]
|
145
|
+
end
|
146
|
+
|
147
|
+
def tid
|
148
|
+
self[:kl_tid]
|
149
|
+
end
|
150
|
+
|
151
|
+
def flags
|
152
|
+
self[:kl_flags]
|
153
|
+
end
|
154
|
+
|
155
|
+
def stat
|
156
|
+
self[:kl_stat]
|
157
|
+
end
|
158
|
+
|
159
|
+
def lock
|
160
|
+
self[:kl_lock]
|
161
|
+
end
|
162
|
+
|
163
|
+
def tdflags
|
164
|
+
self[:kl_tdflags]
|
165
|
+
end
|
166
|
+
|
167
|
+
def prio
|
168
|
+
self[:kl_prio]
|
169
|
+
end
|
170
|
+
|
171
|
+
def tdprio
|
172
|
+
self[:kl_tdprio]
|
173
|
+
end
|
174
|
+
|
175
|
+
def rtprio
|
176
|
+
self[:kl_rtprio]
|
177
|
+
end
|
178
|
+
|
179
|
+
def uticks
|
180
|
+
self[:kl_uticks]
|
181
|
+
end
|
182
|
+
|
183
|
+
def sticks
|
184
|
+
self[:kl_sticks]
|
185
|
+
end
|
186
|
+
|
187
|
+
def iticks
|
188
|
+
self[:kl_iticks]
|
189
|
+
end
|
190
|
+
|
191
|
+
def cpticks
|
192
|
+
self[:kl_cpticks]
|
193
|
+
end
|
194
|
+
|
195
|
+
def pctcpu
|
196
|
+
self[:kl_pctcpu]
|
197
|
+
end
|
198
|
+
|
199
|
+
def slptime
|
200
|
+
self[:kl_slptime]
|
201
|
+
end
|
202
|
+
|
203
|
+
def origcpu
|
204
|
+
self[:kl_origcpu]
|
205
|
+
end
|
206
|
+
|
207
|
+
def estcpu
|
208
|
+
self[:kl_estcpu]
|
209
|
+
end
|
210
|
+
|
211
|
+
def cpuid
|
212
|
+
self[:kl_cpuid]
|
213
|
+
end
|
214
|
+
|
215
|
+
def ru
|
216
|
+
self[:kl_ru]
|
217
|
+
end
|
218
|
+
|
219
|
+
def siglist
|
220
|
+
self[:kl_siglist]
|
221
|
+
end
|
222
|
+
|
223
|
+
def sigmask
|
224
|
+
self[:kl_sigmask]
|
225
|
+
end
|
226
|
+
|
227
|
+
def wchan
|
228
|
+
self[:kl_wchan]
|
229
|
+
end
|
230
|
+
|
231
|
+
def wmesg
|
232
|
+
self[:kl_wmesg].to_s
|
233
|
+
end
|
234
|
+
|
235
|
+
def comm
|
236
|
+
self[:kl_comm].to_s
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
class KInfoProc < FFI::Struct
|
241
|
+
include Sys::ProcTableConstants
|
242
|
+
|
243
|
+
def self.roundup(x, y)
|
244
|
+
((x + y-1) / y) * y
|
245
|
+
end
|
246
|
+
|
247
|
+
layout(
|
248
|
+
:kp_paddr, :uintptr_t,
|
249
|
+
:kp_flags, :int,
|
250
|
+
:kp_stat, :procstat,
|
251
|
+
:kp_lock, :int,
|
252
|
+
:kp_acflag, :int,
|
253
|
+
:kp_traceflag, :int,
|
254
|
+
:kp_fd, :uintptr_t,
|
255
|
+
:kp_siglist, Sigset,
|
256
|
+
:kp_sigignore, Sigset,
|
257
|
+
:kp_sigcatch, Sigset,
|
258
|
+
:kp_sigflag, :int,
|
259
|
+
:kp_start, Timeval,
|
260
|
+
:kp_comm, [:char, MAXCOMLEN+1],
|
261
|
+
:kp_uid, :uid_t,
|
262
|
+
:kp_ngroups, :short,
|
263
|
+
:kp_groups, [:gid_t, NGROUPS],
|
264
|
+
:kp_ruid, :uid_t,
|
265
|
+
:kp_svuid, :uid_t,
|
266
|
+
:kp_rgid, :gid_t,
|
267
|
+
:kp_svgid, :gid_t,
|
268
|
+
:kp_pid, :pid_t,
|
269
|
+
:kp_ppid, :pid_t,
|
270
|
+
:kp_pgid, :pid_t,
|
271
|
+
:kp_jobc, :int,
|
272
|
+
:kp_sid, :pid_t,
|
273
|
+
:kp_login, [:char, roundup(MAXLOGNAME, FFI::Type::LONG.size)],
|
274
|
+
:kp_tdev, :dev_t,
|
275
|
+
:kp_tpgid, :pid_t,
|
276
|
+
:kp_tsid, :pid_t,
|
277
|
+
:kp_exitstat, :ushort,
|
278
|
+
:kp_nthreads, :int,
|
279
|
+
:kp_nice, :int,
|
280
|
+
:kp_swtime, :uint,
|
281
|
+
:kp_vm_map_size, :size_t,
|
282
|
+
:kp_vm_rssize, :segsz_t,
|
283
|
+
:kp_vm_swrss, :segsz_t,
|
284
|
+
:kp_vm_tsize, :segsz_t,
|
285
|
+
:kp_vm_dsize, :segsz_t,
|
286
|
+
:kp_vm_ssize, :segsz_t,
|
287
|
+
:kp_vm_prssize, :uint,
|
288
|
+
:kp_jailid, :int,
|
289
|
+
:kp_ru, Rusage,
|
290
|
+
:kp_cru, Rusage,
|
291
|
+
:kp_auxflags, :int,
|
292
|
+
:kp_lwp, KInfoLWP,
|
293
|
+
:kp_ktaddr, :uintptr_t,
|
294
|
+
:kp_spare, [:int, 2]
|
295
|
+
)
|
296
|
+
end
|
297
|
+
end
|
298
|
+
end
|
@@ -0,0 +1,175 @@
|
|
1
|
+
require_relative 'proctable/constants'
|
2
|
+
require_relative 'proctable/structs'
|
3
|
+
require_relative 'proctable/functions'
|
4
|
+
require 'sys/proctable/version'
|
5
|
+
|
6
|
+
module Sys
|
7
|
+
class ProcTable
|
8
|
+
include Sys::ProcTableConstants
|
9
|
+
include Sys::ProcTableStructs
|
10
|
+
extend Sys::ProcTableFunctions
|
11
|
+
|
12
|
+
# Error typically raised if the ProcTable.ps method fails.
|
13
|
+
class Error < StandardError; end
|
14
|
+
|
15
|
+
# There is no constructor
|
16
|
+
private_class_method :new
|
17
|
+
|
18
|
+
@fields = %w[
|
19
|
+
paddr flags stat lock acflag traceflag fd siglist sigignore
|
20
|
+
sigcatch sigflag start comm uid ngroups groups ruid svuid
|
21
|
+
rgid svgid pid ppid pgid jobc sid login tdev tpgid tsid exitstat
|
22
|
+
nthreads nice swtime vm_map_size vm_rssize vm_swrss vm_tsize
|
23
|
+
vm_dsize vm_ssize vm_prssize jailid ru cru auxflags lwp ktaddr
|
24
|
+
]
|
25
|
+
|
26
|
+
ProcTableStruct = Struct.new('ProcTableStruct', *@fields) do
|
27
|
+
alias cmdline comm
|
28
|
+
end
|
29
|
+
|
30
|
+
# In block form, yields a ProcTableStruct for each process entry that you
|
31
|
+
# have rights to. This method returns an array of ProcTableStruct's in
|
32
|
+
# non-block form.
|
33
|
+
#
|
34
|
+
# If a +pid+ is provided, then only a single ProcTableStruct is yielded or
|
35
|
+
# returned, or nil if no process information is found for that +pid+.
|
36
|
+
#
|
37
|
+
# Example:
|
38
|
+
#
|
39
|
+
# # Iterate over all processes
|
40
|
+
# ProcTable.ps do |proc_info|
|
41
|
+
# p proc_info
|
42
|
+
# end
|
43
|
+
#
|
44
|
+
# # Print process table information for only pid 1001
|
45
|
+
# p ProcTable.ps(pid: 1001)
|
46
|
+
#
|
47
|
+
def self.ps(**kwargs)
|
48
|
+
pid = kwargs[:pid]
|
49
|
+
|
50
|
+
begin
|
51
|
+
kd = kvm_open(nil, nil, nil, 0, nil)
|
52
|
+
|
53
|
+
if kd.null?
|
54
|
+
raise SystemCallError.new('kvm_open', FFI.errno)
|
55
|
+
end
|
56
|
+
|
57
|
+
ptr = FFI::MemoryPointer.new(:int) # count
|
58
|
+
|
59
|
+
if pid
|
60
|
+
procs = kvm_getprocs(kd, KERN_PROC_PID, pid, ptr)
|
61
|
+
else
|
62
|
+
procs = kvm_getprocs(kd, KERN_PROC_ALL, 0, ptr)
|
63
|
+
end
|
64
|
+
|
65
|
+
if procs.null?
|
66
|
+
if pid && FFI.errno == Errno::ESRCH::Errno
|
67
|
+
return nil
|
68
|
+
else
|
69
|
+
raise SystemCallError.new('kvm_getprocs', FFI.errno)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
count = ptr.read_int
|
74
|
+
array = []
|
75
|
+
|
76
|
+
0.upto(count-1){ |i|
|
77
|
+
cmd = nil
|
78
|
+
kinfo = KInfoProc.new(procs[i * KInfoProc.size])
|
79
|
+
|
80
|
+
args = kvm_getargv(kd, kinfo, 0)
|
81
|
+
|
82
|
+
unless args.null?
|
83
|
+
cmd = []
|
84
|
+
|
85
|
+
until ((ptr = args.read_pointer).null?)
|
86
|
+
cmd << ptr.read_string
|
87
|
+
args += FFI::Type::POINTER.size
|
88
|
+
end
|
89
|
+
|
90
|
+
cmd = cmd.join(' ')
|
91
|
+
end
|
92
|
+
|
93
|
+
struct = ProcTableStruct.new(
|
94
|
+
kinfo[:kp_paddr],
|
95
|
+
kinfo[:kp_flags],
|
96
|
+
kinfo[:kp_stat],
|
97
|
+
kinfo[:kp_lock],
|
98
|
+
kinfo[:kp_acflag],
|
99
|
+
kinfo[:kp_traceflag],
|
100
|
+
kinfo[:kp_fd],
|
101
|
+
kinfo[:kp_siglist].bits,
|
102
|
+
kinfo[:kp_sigignore].bits,
|
103
|
+
kinfo[:kp_sigcatch].bits,
|
104
|
+
kinfo[:kp_sigflag],
|
105
|
+
Time.at(kinfo[:kp_start][:tv_sec]),
|
106
|
+
kinfo[:kp_comm].to_s,
|
107
|
+
kinfo[:kp_uid],
|
108
|
+
kinfo[:kp_ngroups],
|
109
|
+
kinfo[:kp_groups].to_a[0..kinfo[:kp_ngroups]-1],
|
110
|
+
kinfo[:kp_ruid],
|
111
|
+
kinfo[:kp_svuid],
|
112
|
+
kinfo[:kp_rgid],
|
113
|
+
kinfo[:kp_svgid],
|
114
|
+
kinfo[:kp_pid],
|
115
|
+
kinfo[:kp_ppid],
|
116
|
+
kinfo[:kp_pgid],
|
117
|
+
kinfo[:kp_jobc],
|
118
|
+
kinfo[:kp_sid],
|
119
|
+
kinfo[:kp_login].to_s,
|
120
|
+
kinfo[:kp_tdev],
|
121
|
+
kinfo[:kp_tpgid],
|
122
|
+
kinfo[:kp_tsid],
|
123
|
+
kinfo[:kp_exitstat],
|
124
|
+
kinfo[:kp_nthreads],
|
125
|
+
kinfo[:kp_nice],
|
126
|
+
kinfo[:kp_swtime],
|
127
|
+
kinfo[:kp_vm_map_size],
|
128
|
+
kinfo[:kp_vm_rssize],
|
129
|
+
kinfo[:kp_vm_swrss],
|
130
|
+
kinfo[:kp_vm_tsize],
|
131
|
+
kinfo[:kp_vm_dsize],
|
132
|
+
kinfo[:kp_vm_ssize],
|
133
|
+
kinfo[:kp_vm_prssize],
|
134
|
+
kinfo[:kp_jailid],
|
135
|
+
kinfo[:kp_ru],
|
136
|
+
kinfo[:kp_cru],
|
137
|
+
kinfo[:kp_auxflags],
|
138
|
+
kinfo[:kp_lwp],
|
139
|
+
kinfo[:kp_ktaddr],
|
140
|
+
)
|
141
|
+
|
142
|
+
struct.freeze # This is readonly data
|
143
|
+
|
144
|
+
if block_given?
|
145
|
+
yield struct
|
146
|
+
else
|
147
|
+
array << struct
|
148
|
+
end
|
149
|
+
}
|
150
|
+
ensure
|
151
|
+
kvm_close(kd) unless kd.null?
|
152
|
+
end
|
153
|
+
|
154
|
+
if block_given?
|
155
|
+
nil
|
156
|
+
else
|
157
|
+
pid ? array.first : array
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
# Returns an array of fields that each ProcTableStruct will contain. This
|
162
|
+
# may be useful if you want to know in advance what fields are available
|
163
|
+
# without having to perform at least one read of the /proc table.
|
164
|
+
#
|
165
|
+
# Example:
|
166
|
+
#
|
167
|
+
# Sys::ProcTable.fields.each{ |field|
|
168
|
+
# puts "Field: #{field}"
|
169
|
+
# }
|
170
|
+
#
|
171
|
+
def self.fields
|
172
|
+
@fields
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
data/lib/darwin/sys/proctable.rb
CHANGED
@@ -11,21 +11,32 @@ module Sys
|
|
11
11
|
# There is no constructor
|
12
12
|
private_class_method :new
|
13
13
|
|
14
|
-
private
|
15
|
-
|
16
14
|
PROC_PIDTASKALLINFO = 2
|
17
15
|
PROC_PIDTHREADINFO = 5
|
18
16
|
PROC_PIDLISTTHREADS = 6
|
19
17
|
|
18
|
+
private_constant :PROC_PIDTASKALLINFO
|
19
|
+
private_constant :PROC_PIDTHREADINFO
|
20
|
+
private_constant :PROC_PIDLISTTHREADS
|
21
|
+
|
20
22
|
CTL_KERN = 1
|
21
23
|
KERN_PROCARGS = 38
|
22
24
|
KERN_PROCARGS2 = 49
|
23
25
|
MAXCOMLEN = 16
|
24
26
|
MAXPATHLEN = 256
|
25
27
|
|
28
|
+
private_constant :CTL_KERN
|
29
|
+
private_constant :KERN_PROCARGS
|
30
|
+
private_constant :KERN_PROCARGS2
|
31
|
+
private_constant :MAXCOMLEN
|
32
|
+
private_constant :MAXPATHLEN
|
33
|
+
|
26
34
|
MAXTHREADNAMESIZE = 64
|
27
35
|
PROC_PIDPATHINFO_MAXSIZE = MAXPATHLEN * 4
|
28
36
|
|
37
|
+
private_constant :MAXTHREADNAMESIZE
|
38
|
+
private_constant :PROC_PIDPATHINFO_MAXSIZE
|
39
|
+
|
29
40
|
# JRuby/Truffleruby on Mac
|
30
41
|
unless defined? FFI::StructLayout::CharArray
|
31
42
|
if defined? FFI::StructLayout::CharArrayProxy
|
@@ -62,6 +73,8 @@ module Sys
|
|
62
73
|
)
|
63
74
|
end
|
64
75
|
|
76
|
+
private_constant :ProcBsdInfo
|
77
|
+
|
65
78
|
class ProcTaskInfo < FFI::Struct
|
66
79
|
layout(
|
67
80
|
:pti_virtual_size, :uint64_t,
|
@@ -85,6 +98,8 @@ module Sys
|
|
85
98
|
)
|
86
99
|
end
|
87
100
|
|
101
|
+
private_constant :ProcTaskInfo
|
102
|
+
|
88
103
|
class ProcThreadInfo < FFI::Struct
|
89
104
|
layout(
|
90
105
|
:pth_user_time, :uint64_t,
|
@@ -101,28 +116,37 @@ module Sys
|
|
101
116
|
)
|
102
117
|
end
|
103
118
|
|
119
|
+
private_constant :ProcThreadInfo
|
120
|
+
|
104
121
|
# Map the fields from the FFI::Structs to the Sys::ProcTable struct on
|
105
122
|
# class load to reduce the amount of objects needing to be generated for
|
106
123
|
# each invocation of Sys::ProcTable.ps
|
107
|
-
all_members
|
108
|
-
|
124
|
+
all_members = ProcBsdInfo.members + ProcTaskInfo.members + ProcThreadInfo.members
|
125
|
+
|
126
|
+
PROC_STRUCT_FIELD_MAP = all_members.map do |member|
|
109
127
|
temp = member.to_s.split('_')
|
110
128
|
sproperty = temp.size > 1 ? temp[1..-1].join('_') : temp.first
|
111
129
|
[member, sproperty.to_sym]
|
112
|
-
|
130
|
+
end.to_h
|
113
131
|
|
114
132
|
class ProcTaskAllInfo < FFI::Struct
|
115
133
|
layout(:pbsd, ProcBsdInfo, :ptinfo, ProcTaskInfo)
|
116
134
|
end
|
117
135
|
|
136
|
+
private_constant :ProcTaskAllInfo
|
137
|
+
|
118
138
|
ffi_lib 'proc'
|
119
139
|
|
120
|
-
attach_function :proc_listallpids, [
|
121
|
-
attach_function :proc_pidinfo, [
|
140
|
+
attach_function :proc_listallpids, %i[pointer int], :int
|
141
|
+
attach_function :proc_pidinfo, %i[int int uint64_t pointer int], :int
|
122
142
|
|
123
143
|
ffi_lib FFI::Library::LIBC
|
124
144
|
|
125
|
-
attach_function :sysctl, [
|
145
|
+
attach_function :sysctl, %i[pointer uint pointer pointer pointer size_t], :int
|
146
|
+
|
147
|
+
private_class_method :proc_listallpids
|
148
|
+
private_class_method :proc_pidinfo
|
149
|
+
private_class_method :sysctl
|
126
150
|
|
127
151
|
# These mostly mimic the struct members, but we've added a few custom ones as well.
|
128
152
|
@fields = %w[
|
@@ -136,16 +160,18 @@ module Sys
|
|
136
160
|
|
137
161
|
# Add a couple aliases to make it similar to Linux
|
138
162
|
ProcTableStruct = Struct.new("ProcTableStruct", *@fields) do
|
139
|
-
|
140
|
-
|
163
|
+
alias_method :vsize, :virtual_size
|
164
|
+
alias_method :rss, :resident_size
|
141
165
|
end
|
142
166
|
|
167
|
+
private_constant :ProcTableStruct
|
168
|
+
|
143
169
|
ThreadInfoStruct = Struct.new("ThreadInfo", :user_time, :system_time,
|
144
170
|
:cpu_usage, :policy, :run_state, :flags, :sleep_time, :curpri,
|
145
171
|
:priority, :maxpriority, :name
|
146
172
|
)
|
147
173
|
|
148
|
-
|
174
|
+
private_constant :ThreadInfoStruct
|
149
175
|
|
150
176
|
# Returns an array of fields that each ProcTableStruct will contain. This
|
151
177
|
# may be useful if you want to know in advance what fields are available
|
@@ -222,7 +248,7 @@ module Sys
|
|
222
248
|
array = block_given? ? nil : []
|
223
249
|
|
224
250
|
pids.each do |lpid|
|
225
|
-
next
|
251
|
+
next if pid && pid != lpid
|
226
252
|
info = ProcTaskAllInfo.new
|
227
253
|
|
228
254
|
nb = proc_pidinfo(lpid, PROC_PIDTASKALLINFO, 0, info, info.size)
|
@@ -258,8 +284,6 @@ module Sys
|
|
258
284
|
end
|
259
285
|
end
|
260
286
|
|
261
|
-
private
|
262
|
-
|
263
287
|
# Pass by reference method that updates the Ruby struct based on the FFI struct.
|
264
288
|
#
|
265
289
|
def self.apply_info_to_struct(info, struct)
|
@@ -275,6 +299,8 @@ module Sys
|
|
275
299
|
end
|
276
300
|
end
|
277
301
|
|
302
|
+
private_class_method :apply_info_to_struct
|
303
|
+
|
278
304
|
# Returns an array of ThreadInfo objects for the given pid.
|
279
305
|
#
|
280
306
|
def self.get_thread_info(pid, struct, ptinfo)
|
@@ -292,7 +318,7 @@ module Sys
|
|
292
318
|
max = ptinfo[:pti_threadnum]
|
293
319
|
struct[:threadinfo] = []
|
294
320
|
|
295
|
-
0.upto(max-1) do |index|
|
321
|
+
0.upto(max - 1) do |index|
|
296
322
|
tinfo = ProcThreadInfo.new
|
297
323
|
|
298
324
|
# Use read_array_of_uint64 for compatibility with JRuby if necessary.
|
@@ -304,7 +330,7 @@ module Sys
|
|
304
330
|
|
305
331
|
if nb <= 0
|
306
332
|
if [Errno::EPERM::Errno, Errno::ESRCH::Errno].include?(FFI.errno)
|
307
|
-
|
333
|
+
next # Either we don't have permission, or the pid no longer exists
|
308
334
|
else
|
309
335
|
raise SystemCallError.new('proc_pidinfo', FFI.errno)
|
310
336
|
end
|
@@ -321,15 +347,21 @@ module Sys
|
|
321
347
|
tinfo[:pth_curpri],
|
322
348
|
tinfo[:pth_priority],
|
323
349
|
tinfo[:pth_maxpriority],
|
324
|
-
tinfo[:pth_name].to_s
|
350
|
+
tinfo[:pth_name].to_s
|
325
351
|
)
|
326
352
|
|
327
353
|
struct[:threadinfo] << tinfo_struct
|
328
354
|
end
|
329
355
|
end
|
330
356
|
|
357
|
+
private_class_method :get_thread_info
|
358
|
+
|
331
359
|
# Get the command line arguments, as well as the environment settings,
|
332
360
|
# for the given PID.
|
361
|
+
#--
|
362
|
+
# Note that on Big Sur and later it seems that you cannot get environment
|
363
|
+
# variable information on spawned processes except in certain circumstances,
|
364
|
+
# e.g. SIP has been disabled, the kernel is in debug mode, etc.
|
333
365
|
#
|
334
366
|
def self.get_cmd_args_and_env(pid, struct)
|
335
367
|
len = FFI::MemoryPointer.new(:size_t)
|
@@ -389,22 +421,23 @@ module Sys
|
|
389
421
|
|
390
422
|
# Extract the full command line and its arguments from the array
|
391
423
|
argc.times do
|
392
|
-
cmdline << ' '
|
424
|
+
cmdline << ' ' << array.shift
|
393
425
|
end
|
394
426
|
|
395
427
|
struct[:cmdline] = cmdline.strip
|
396
428
|
|
397
429
|
# Anything remaining at this point is a collection of key=value
|
398
430
|
# pairs which we convert into a hash.
|
399
|
-
environ = array.
|
431
|
+
environ = array.each_with_object({}) do |string, hash|
|
400
432
|
if string && string.include?('=')
|
401
433
|
key, value = string.split('=')
|
402
434
|
hash[key] = value
|
403
435
|
end
|
404
|
-
hash
|
405
436
|
end
|
406
437
|
|
407
438
|
struct[:environ] = environ
|
408
439
|
end
|
440
|
+
|
441
|
+
private_class_method :get_cmd_args_and_env
|
409
442
|
end
|
410
443
|
end
|