sys-proctable 0.9.4-universal-darwin → 0.9.5-universal-darwin
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
- data/CHANGES +6 -0
- data/Rakefile +2 -0
- data/ext/darwin/sys/proctable.c +257 -213
- data/sys-proctable.gemspec +1 -1
- data/test/test_sys_proctable_all.rb +7 -1
- data/test/test_sys_proctable_darwin.rb +60 -4
- data/test/test_sys_top.rb +46 -0
- metadata +5 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3b1cdd14b7384e61fcbaebc7cb065b44a9e93c45
|
4
|
+
data.tar.gz: 42ba4f461988cb3cddb6509e5e650e7acbf6cd02
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b94812963041c9a7870fcd5ad145f0b1d0d7e4374fd7e37b7ce13ac19aa5246a19bf8870c09523ec71a4ff9e4ab9aecaba5a263eb79b3708b3b12a5f79830e4d
|
7
|
+
data.tar.gz: 90a56eff492e110906c5d14b199dabc6964919e933405f39ebe97079867d5a9d9f36970f7df7d1ad78ab48efec7470c4cd3f73958a7ca800e52bfa2aed2226d6
|
data/CHANGES
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 0.9.5 - 10-Feb-2015
|
2
|
+
* Significant cleanup and memory reduction of the OSX code. Thanks go
|
3
|
+
to Ivan (toy) for the patches.
|
4
|
+
* Skip over /proc/<file>/status if unreadable on Linux. Thanks go to Jianjun
|
5
|
+
Mao for the patch.
|
6
|
+
|
1
7
|
== 0.9.4 - 4-Mar-2014
|
2
8
|
* Added support for AIX 5.3 or later courtesy of Rick Ohnemus.
|
3
9
|
* The Solaris version now uses FFI structs instead of a packed array.
|
data/Rakefile
CHANGED
@@ -174,6 +174,8 @@ namespace :gem do
|
|
174
174
|
spec.files += ['lib/windows/sys/proctable.rb']
|
175
175
|
spec.test_files << 'test/test_sys_proctable_windows.rb'
|
176
176
|
end
|
177
|
+
|
178
|
+
spec.test_files << 'test/test_sys_top.rb'
|
177
179
|
|
178
180
|
# https://github.com/rubygems/rubygems/issues/147
|
179
181
|
spec.original_platform = spec.platform
|
data/ext/darwin/sys/proctable.c
CHANGED
@@ -20,7 +20,7 @@
|
|
20
20
|
|
21
21
|
#define pid_of(pproc) pproc->kp_proc.p_pid
|
22
22
|
|
23
|
-
#define SYS_PROCTABLE_VERSION "0.9.
|
23
|
+
#define SYS_PROCTABLE_VERSION "0.9.5"
|
24
24
|
|
25
25
|
#define PROC_MIB_LEN 4
|
26
26
|
#define ARGS_MIB_LEN 3
|
@@ -31,15 +31,7 @@
|
|
31
31
|
|
32
32
|
VALUE cProcTableError, sProcStruct;
|
33
33
|
|
34
|
-
|
35
|
-
"pid", "ppid", "pgid", "ruid", "rgid", "comm", "state", "pctcpu", "oncpu",
|
36
|
-
"tnum", "tdev", "wmesg", "rtime", "priority", "usrpri", "nice", "cmdline",
|
37
|
-
"starttime", "maxrss", "ixrss", "idrss", "isrss", "minflt", "majflt",
|
38
|
-
"nswap", "inblock", "oublock", "msgsnd", "msgrcv", "nsignals", "nvcsw",
|
39
|
-
"nivcsw", "utime", "stime"
|
40
|
-
};
|
41
|
-
|
42
|
-
int argv_of_pid(int pid, char* cmdline) {
|
34
|
+
int argv_of_pid(int pid, VALUE* v_cmdline, VALUE* v_exe, VALUE* v_environ) {
|
43
35
|
int mib[3], argmax, nargs, c = 0;
|
44
36
|
size_t size;
|
45
37
|
char *procargs, *sp, *np, *cp;
|
@@ -116,6 +108,9 @@ int argv_of_pid(int pid, char* cmdline) {
|
|
116
108
|
memcpy(&nargs, procargs, sizeof(nargs));
|
117
109
|
cp = procargs + sizeof(nargs);
|
118
110
|
|
111
|
+
/* Copy exec_path to ruby String. */
|
112
|
+
*v_exe = rb_str_new2(cp);
|
113
|
+
|
119
114
|
/* Skip the saved exec_path. */
|
120
115
|
for (; cp < &procargs[size]; cp++) {
|
121
116
|
if (*cp == '\0') {
|
@@ -151,22 +146,22 @@ int argv_of_pid(int pid, char* cmdline) {
|
|
151
146
|
if (*cp == '\0') {
|
152
147
|
c++;
|
153
148
|
if (np != NULL) {
|
154
|
-
|
155
|
-
|
149
|
+
/* Convert previous '\0'. */
|
150
|
+
*np = ' ';
|
156
151
|
} else {
|
157
|
-
|
152
|
+
/* *argv0len = cp - sp; */
|
158
153
|
}
|
159
154
|
/* Note location of current '\0'. */
|
160
155
|
np = cp;
|
161
156
|
|
162
157
|
if (!show_args) {
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
158
|
+
/*
|
159
|
+
* Don't convert '\0' characters to ' '.
|
160
|
+
* However, we needed to know that the
|
161
|
+
* command name was terminated, which we
|
162
|
+
* now know.
|
163
|
+
*/
|
164
|
+
break;
|
170
165
|
}
|
171
166
|
}
|
172
167
|
}
|
@@ -180,8 +175,19 @@ int argv_of_pid(int pid, char* cmdline) {
|
|
180
175
|
goto ERROR_B;
|
181
176
|
}
|
182
177
|
|
183
|
-
/* Make a copy of the string. */
|
184
|
-
|
178
|
+
/* Make a copy of the string to ruby String. */
|
179
|
+
*v_cmdline = rb_str_new2(sp);
|
180
|
+
|
181
|
+
/* Read environment variables to ruby Hash. */
|
182
|
+
*v_environ = rb_hash_new();
|
183
|
+
while (cp[0]) {
|
184
|
+
sp = strsep(&cp, "=");
|
185
|
+
if (sp == NULL) {
|
186
|
+
break;
|
187
|
+
}
|
188
|
+
rb_hash_aset(*v_environ, rb_str_new2(sp), rb_str_new2(cp));
|
189
|
+
cp += strlen(cp) + 1;
|
190
|
+
}
|
185
191
|
|
186
192
|
/* Clean up. */
|
187
193
|
free(procargs);
|
@@ -206,163 +212,161 @@ int argv_of_pid(int pid, char* cmdline) {
|
|
206
212
|
* returned, or nil if no process information is found for that +pid+.
|
207
213
|
*/
|
208
214
|
static VALUE pt_ps(int argc, VALUE* argv, VALUE klass){
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
215
|
+
int err;
|
216
|
+
char state[8];
|
217
|
+
struct kinfo_proc* procs;
|
218
|
+
VALUE v_pid, v_tty_num, v_tty_dev, v_start_time;
|
219
|
+
VALUE v_pstruct = Qnil;
|
220
|
+
VALUE v_array = rb_ary_new();
|
221
|
+
size_t length, count;
|
222
|
+
size_t i = 0;
|
223
|
+
int g;
|
224
|
+
VALUE v_cmdline, v_exe, v_environ, v_groups;
|
225
|
+
|
226
|
+
// Passed into sysctl call
|
227
|
+
static const int name_mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
|
228
|
+
|
229
|
+
rb_scan_args(argc, argv, "01", &v_pid);
|
230
|
+
|
231
|
+
// Get size of proc kproc buffer
|
232
|
+
err = sysctl( (int *) name_mib, PROC_MIB_LEN, NULL, &length, NULL, 0);
|
233
|
+
|
234
|
+
if(err == -1)
|
235
|
+
rb_raise(cProcTableError, "sysctl: %s", strerror(errno));
|
236
|
+
|
237
|
+
// Populate the kproc buffer
|
238
|
+
procs = malloc(length);
|
239
|
+
|
240
|
+
if(procs == NULL)
|
241
|
+
rb_raise(cProcTableError, "malloc: %s", strerror(errno));
|
242
|
+
|
243
|
+
err = sysctl( (int *) name_mib, PROC_MIB_LEN, procs, &length, NULL, 0);
|
244
|
+
|
245
|
+
if(err == -1)
|
246
|
+
rb_raise(cProcTableError, "sysctl: %s", strerror(errno));
|
247
|
+
|
248
|
+
// If we're here, we got our list
|
249
|
+
count = length / sizeof(struct kinfo_proc);
|
250
|
+
|
251
|
+
for(i = 0; i < count; i++) {
|
252
|
+
v_tty_num = Qnil;
|
253
|
+
v_tty_dev = Qnil;
|
254
|
+
v_start_time = Qnil;
|
255
|
+
|
256
|
+
// If a PID is provided, skip unless the PID matches
|
257
|
+
if( (!NIL_P(v_pid)) && (procs[i].kp_proc.p_pid != NUM2INT(v_pid)) )
|
258
|
+
continue;
|
259
|
+
|
260
|
+
// cmdline will be set only if process exists and belongs to current user or
|
261
|
+
// current user is root
|
262
|
+
v_cmdline = Qnil;
|
263
|
+
v_exe = Qnil;
|
264
|
+
v_environ = Qnil;
|
265
|
+
argv_of_pid(procs[i].kp_proc.p_pid, &v_cmdline, &v_exe, &v_environ);
|
266
|
+
|
267
|
+
// Get the start time of the process
|
268
|
+
v_start_time = rb_time_new(
|
269
|
+
procs[i].kp_proc.p_un.__p_starttime.tv_sec,
|
270
|
+
procs[i].kp_proc.p_un.__p_starttime.tv_usec
|
271
|
+
);
|
272
|
+
|
273
|
+
// Get the state of the process
|
274
|
+
switch(procs[i].kp_proc.p_stat)
|
275
|
+
{
|
276
|
+
case SIDL:
|
277
|
+
strcpy(state, "idle");
|
278
|
+
break;
|
279
|
+
case SRUN:
|
280
|
+
strcpy(state, "run");
|
281
|
+
break;
|
282
|
+
case SSLEEP:
|
283
|
+
strcpy(state, "sleep");
|
284
|
+
break;
|
285
|
+
case SSTOP:
|
286
|
+
strcpy(state, "stop");
|
287
|
+
break;
|
288
|
+
case SZOMB:
|
289
|
+
strcpy(state, "zombie");
|
290
|
+
break;
|
291
|
+
default:
|
292
|
+
strcpy(state, "unknown");
|
293
|
+
break;
|
294
|
+
}
|
252
295
|
|
253
|
-
|
296
|
+
// Get ttynum and ttydev. If ttynum is -1, there is no tty.
|
297
|
+
if(procs[i].kp_eproc.e_tdev != -1){
|
298
|
+
v_tty_num = INT2FIX(procs[i].kp_eproc.e_tdev),
|
299
|
+
v_tty_dev = rb_str_new2(devname(procs[i].kp_eproc.e_tdev, S_IFCHR));
|
300
|
+
}
|
254
301
|
|
255
|
-
|
256
|
-
|
302
|
+
v_groups = rb_ary_new();
|
303
|
+
for (g = 0; g < procs[i].kp_eproc.e_ucred.cr_ngroups; ++g) {
|
304
|
+
rb_ary_push(v_groups, INT2FIX(procs[i].kp_eproc.e_ucred.cr_groups[g]));
|
305
|
+
}
|
257
306
|
|
258
|
-
|
259
|
-
|
307
|
+
v_pstruct = rb_struct_new(
|
308
|
+
sProcStruct,
|
309
|
+
INT2FIX(procs[i].kp_proc.p_pid),
|
310
|
+
INT2FIX(procs[i].kp_eproc.e_ppid),
|
311
|
+
INT2FIX(procs[i].kp_eproc.e_pgid),
|
312
|
+
INT2FIX(procs[i].kp_eproc.e_pcred.p_ruid),
|
313
|
+
INT2FIX(procs[i].kp_eproc.e_pcred.p_rgid),
|
314
|
+
INT2FIX(procs[i].kp_eproc.e_ucred.cr_uid),
|
315
|
+
rb_ary_entry(v_groups, 0),
|
316
|
+
v_groups,
|
317
|
+
INT2FIX(procs[i].kp_eproc.e_pcred.p_svuid),
|
318
|
+
INT2FIX(procs[i].kp_eproc.e_pcred.p_svgid),
|
319
|
+
rb_str_new2(procs[i].kp_proc.p_comm),
|
320
|
+
rb_str_new2(state),
|
321
|
+
rb_float_new(procs[i].kp_proc.p_pctcpu),
|
322
|
+
Qnil,
|
323
|
+
v_tty_num,
|
324
|
+
v_tty_dev,
|
325
|
+
rb_str_new2(procs[i].kp_eproc.e_wmesg),
|
326
|
+
INT2FIX(procs[i].kp_proc.p_rtime.tv_sec),
|
327
|
+
INT2FIX(procs[i].kp_proc.p_priority),
|
328
|
+
INT2FIX(procs[i].kp_proc.p_usrpri),
|
329
|
+
INT2FIX(procs[i].kp_proc.p_nice),
|
330
|
+
v_cmdline,
|
331
|
+
v_exe,
|
332
|
+
v_environ,
|
333
|
+
v_start_time,
|
334
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_maxrss) : Qnil,
|
335
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_ixrss) : Qnil,
|
336
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_idrss) : Qnil,
|
337
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_isrss) : Qnil,
|
338
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_minflt) : Qnil,
|
339
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_majflt) : Qnil,
|
340
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nswap) : Qnil,
|
341
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_inblock) : Qnil,
|
342
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_oublock) : Qnil,
|
343
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgsnd) : Qnil,
|
344
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgrcv) : Qnil,
|
345
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nsignals) : Qnil,
|
346
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nvcsw) : Qnil,
|
347
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nivcsw) : Qnil,
|
348
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_utime.tv_sec) : Qnil,
|
349
|
+
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_stime.tv_sec) : Qnil
|
350
|
+
);
|
351
|
+
|
352
|
+
OBJ_FREEZE(v_pstruct); // This is read-only data
|
353
|
+
|
354
|
+
if(rb_block_given_p())
|
355
|
+
rb_yield(v_pstruct);
|
356
|
+
else
|
357
|
+
rb_ary_push(v_array, v_pstruct);
|
358
|
+
}
|
260
359
|
|
261
|
-
|
262
|
-
fprintf(stderr, "Ret: %d LEN: %d\n", err, args_size);
|
263
|
-
char *c;
|
264
|
-
for(c = args; c < args+args_size; c++)
|
265
|
-
if(*c == '\0') *c = ' ';
|
266
|
-
args[args_size] = '\0';
|
267
|
-
} else {
|
268
|
-
fprintf(stderr, "err: %s LEN: %d\n", strerror(errno), args_size);
|
269
|
-
}*/
|
270
|
-
char cmdline[ARGS_MAX_LEN+1];
|
271
|
-
|
272
|
-
argv_of_pid(procs[i].kp_proc.p_pid, cmdline);
|
273
|
-
// free(cmdline);
|
274
|
-
|
275
|
-
// Get the start time of the process
|
276
|
-
v_start_time = rb_time_new(
|
277
|
-
procs[i].kp_proc.p_un.__p_starttime.tv_sec,
|
278
|
-
procs[i].kp_proc.p_un.__p_starttime.tv_usec
|
279
|
-
);
|
280
|
-
|
281
|
-
// Get the state of the process
|
282
|
-
switch(procs[i].kp_proc.p_stat)
|
283
|
-
{
|
284
|
-
case SIDL:
|
285
|
-
strcpy(state, "idle");
|
286
|
-
break;
|
287
|
-
case SRUN:
|
288
|
-
strcpy(state, "run");
|
289
|
-
break;
|
290
|
-
case SSLEEP:
|
291
|
-
strcpy(state, "sleep");
|
292
|
-
break;
|
293
|
-
case SSTOP:
|
294
|
-
strcpy(state, "stop");
|
295
|
-
break;
|
296
|
-
case SZOMB:
|
297
|
-
strcpy(state, "zombie");
|
298
|
-
break;
|
299
|
-
default:
|
300
|
-
strcpy(state, "unknown");
|
301
|
-
break;
|
302
|
-
}
|
360
|
+
if(procs) free(procs);
|
303
361
|
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
362
|
+
if(!rb_block_given_p()){
|
363
|
+
if(NIL_P(v_pid))
|
364
|
+
return v_array;
|
365
|
+
else
|
366
|
+
return v_pstruct;
|
367
|
+
}
|
309
368
|
|
310
|
-
|
311
|
-
sProcStruct,
|
312
|
-
INT2FIX(procs[i].kp_proc.p_pid),
|
313
|
-
INT2FIX(procs[i].kp_eproc.e_ppid),
|
314
|
-
INT2FIX(procs[i].kp_eproc.e_pgid),
|
315
|
-
INT2FIX(procs[i].kp_eproc.e_pcred.p_ruid),
|
316
|
-
INT2FIX(procs[i].kp_eproc.e_pcred.p_rgid),
|
317
|
-
rb_str_new2(procs[i].kp_proc.p_comm),
|
318
|
-
rb_str_new2(state),
|
319
|
-
rb_float_new(procs[i].kp_proc.p_pctcpu),
|
320
|
-
Qnil,
|
321
|
-
v_tty_num,
|
322
|
-
v_tty_dev,
|
323
|
-
rb_str_new2(procs[i].kp_eproc.e_wmesg),
|
324
|
-
INT2FIX(procs[i].kp_proc.p_rtime.tv_sec),
|
325
|
-
INT2FIX(procs[i].kp_proc.p_priority),
|
326
|
-
INT2FIX(procs[i].kp_proc.p_usrpri),
|
327
|
-
INT2FIX(procs[i].kp_proc.p_nice),
|
328
|
-
rb_str_new2(cmdline),
|
329
|
-
v_start_time,
|
330
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_maxrss) : Qnil,
|
331
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_ixrss) : Qnil,
|
332
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_idrss) : Qnil,
|
333
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_isrss) : Qnil,
|
334
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_minflt) : Qnil,
|
335
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_majflt) : Qnil,
|
336
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nswap) : Qnil,
|
337
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_inblock) : Qnil,
|
338
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_oublock) : Qnil,
|
339
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgsnd) : Qnil,
|
340
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_msgrcv) : Qnil,
|
341
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nsignals) : Qnil,
|
342
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nvcsw) : Qnil,
|
343
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_nivcsw) : Qnil,
|
344
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_utime.tv_sec) : Qnil,
|
345
|
-
(procs[i].kp_proc.p_ru && procs[i].kp_proc.p_stat != 5) ? LONG2NUM(procs[i].kp_proc.p_ru->ru_stime.tv_sec) : Qnil
|
346
|
-
);
|
347
|
-
|
348
|
-
OBJ_FREEZE(v_pstruct); // This is read-only data
|
349
|
-
|
350
|
-
if(rb_block_given_p())
|
351
|
-
rb_yield(v_pstruct);
|
352
|
-
else
|
353
|
-
rb_ary_push(v_array, v_pstruct);
|
354
|
-
}
|
355
|
-
|
356
|
-
if(procs) free(procs);
|
357
|
-
|
358
|
-
if(!rb_block_given_p()){
|
359
|
-
if(NIL_P(v_pid))
|
360
|
-
return v_array;
|
361
|
-
else
|
362
|
-
return v_pstruct;
|
363
|
-
}
|
364
|
-
|
365
|
-
return Qnil;
|
369
|
+
return Qnil;
|
366
370
|
}
|
367
371
|
|
368
372
|
/*
|
@@ -374,52 +378,92 @@ static VALUE pt_ps(int argc, VALUE* argv, VALUE klass){
|
|
374
378
|
* without having to perform at least one read of the /proc table.
|
375
379
|
*/
|
376
380
|
static VALUE pt_fields(VALUE klass){
|
377
|
-
|
378
|
-
|
379
|
-
|
381
|
+
VALUE v_array = rb_ary_new();
|
382
|
+
|
383
|
+
VALUE v_members = rb_struct_s_members(sProcStruct), v_member;
|
384
|
+
long size = RARRAY_LEN(v_members);
|
385
|
+
int i;
|
380
386
|
|
381
|
-
|
382
|
-
|
387
|
+
for(i = 0; i < size; i++) {
|
388
|
+
v_member = rb_funcall(rb_ary_entry(v_members, i), rb_intern("to_s"), 0);
|
389
|
+
rb_ary_push(v_array, v_member);
|
390
|
+
}
|
383
391
|
|
384
|
-
|
392
|
+
return v_array;
|
385
393
|
}
|
386
394
|
|
387
395
|
/*
|
388
396
|
* A Ruby interface for gathering process table information.
|
389
397
|
*/
|
390
398
|
void Init_proctable(){
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
399
|
+
VALUE mSys, cProcTable;
|
400
|
+
|
401
|
+
/* The Sys module serves as a namespace only */
|
402
|
+
mSys = rb_define_module("Sys");
|
403
|
+
|
404
|
+
/* The ProcTable class encapsulates process table information */
|
405
|
+
cProcTable = rb_define_class_under(mSys, "ProcTable", rb_cObject);
|
406
|
+
|
407
|
+
/* The Error class typically raised if any of the ProcTable methods fail */
|
408
|
+
cProcTableError = rb_define_class_under(cProcTable, "Error", rb_eStandardError);
|
409
|
+
|
410
|
+
/* Singleton methods */
|
411
|
+
|
412
|
+
rb_define_singleton_method(cProcTable, "ps", pt_ps, -1);
|
413
|
+
rb_define_singleton_method(cProcTable, "fields", pt_fields, 0);
|
414
|
+
|
415
|
+
/* There is no constructor */
|
416
|
+
rb_funcall(cProcTable, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new")));
|
417
|
+
|
418
|
+
/* Constants */
|
419
|
+
|
420
|
+
/* 0.9.5: The version of the sys-proctable library */
|
421
|
+
rb_define_const(cProcTable, "VERSION", rb_str_new2(SYS_PROCTABLE_VERSION));
|
422
|
+
|
423
|
+
/* Structs */
|
424
|
+
|
425
|
+
sProcStruct = rb_struct_define("ProcTableStruct",
|
426
|
+
"pid", /* Process identifier */
|
427
|
+
"ppid", /* Parent process id */
|
428
|
+
"pgid", /* Process group id */
|
429
|
+
"ruid", /* Real user id */
|
430
|
+
"rgid", /* Real group id */
|
431
|
+
"euid", /* Effective user id */
|
432
|
+
"egid", /* Effective group id */
|
433
|
+
"groups", /* All effective group ids */
|
434
|
+
"svuid", /* Saved effective user id */
|
435
|
+
"svgid", /* Saved effective group id */
|
436
|
+
"comm", /* Command name (15 chars) */
|
437
|
+
"state", /* Process status */
|
438
|
+
"pctcpu", /* %cpu for this process during p_swtime */
|
439
|
+
"oncpu", /* nil */
|
440
|
+
"tnum", /* Controlling tty dev */
|
441
|
+
"tdev", /* Controlling tty name */
|
442
|
+
"wmesg", /* Wchan message */
|
443
|
+
"rtime", /* Real time */
|
444
|
+
"priority", /* Process priority */
|
445
|
+
"usrpri", /* User-priority */
|
446
|
+
"nice", /* Process "nice" value */
|
447
|
+
"cmdline", /* Complete command line */
|
448
|
+
"exe", /* Saved pathname of the executed command */
|
449
|
+
"environ", /* Hash with process environment variables */
|
450
|
+
"starttime", /* Process start time */
|
451
|
+
"maxrss", /* Max resident set size (PL) */
|
452
|
+
"ixrss", /* Integral shared memory size (NU) */
|
453
|
+
"idrss", /* Integral unshared data (NU) */
|
454
|
+
"isrss", /* Integral unshared stack (NU) */
|
455
|
+
"minflt", /* Page reclaims (NU) */
|
456
|
+
"majflt", /* Page faults (NU) */
|
457
|
+
"nswap", /* Swaps (NU) */
|
458
|
+
"inblock", /* Block input operations (atomic) */
|
459
|
+
"oublock", /* Block output operations (atomic) */
|
460
|
+
"msgsnd", /* Messages sent (atomic) */
|
461
|
+
"msgrcv", /* Messages received (atomic) */
|
462
|
+
"nsignals", /* Signals received (atomic) */
|
463
|
+
"nvcsw", /* Voluntary context switches (atomic) */
|
464
|
+
"nivcsw", /* Involuntary context switches (atomic) */
|
465
|
+
"utime", /* User time used (PL) */
|
466
|
+
"stime", /* System time used (PL) */
|
467
|
+
NULL
|
468
|
+
);
|
424
469
|
}
|
425
|
-
|
data/sys-proctable.gemspec
CHANGED
@@ -19,7 +19,7 @@ class TC_ProcTable_All < Test::Unit::TestCase
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def test_version
|
22
|
-
assert_equal('0.9.
|
22
|
+
assert_equal('0.9.5', ProcTable::VERSION)
|
23
23
|
end
|
24
24
|
|
25
25
|
def test_fields
|
@@ -71,6 +71,12 @@ class TC_ProcTable_All < Test::Unit::TestCase
|
|
71
71
|
assert_kind_of(StandardError, Sys::ProcTable::Error.new)
|
72
72
|
end
|
73
73
|
|
74
|
+
def test_from_thread
|
75
|
+
Thread.new do
|
76
|
+
Sys::ProcTable.ps
|
77
|
+
end.value
|
78
|
+
end
|
79
|
+
|
74
80
|
def teardown
|
75
81
|
@pid = nil
|
76
82
|
end
|
@@ -12,15 +12,21 @@ include Sys
|
|
12
12
|
class TC_ProcTable_Darwin < Test::Unit::TestCase
|
13
13
|
def self.startup
|
14
14
|
@@fields = %w/
|
15
|
-
pid ppid pgid ruid rgid
|
16
|
-
|
15
|
+
pid ppid pgid ruid rgid euid egid groups svuid svgid
|
16
|
+
comm state pctcpu oncpu tnum
|
17
|
+
tdev wmesg rtime priority usrpri nice cmdline exe environ starttime
|
17
18
|
maxrss ixrss idrss isrss minflt majflt nswap inblock oublock
|
18
19
|
msgsnd msgrcv nsignals nvcsw nivcsw utime stime
|
19
20
|
/
|
21
|
+
|
22
|
+
@@pid = fork do
|
23
|
+
exec('env', '-i', 'A=B', 'Z=', 'sleep', '60')
|
24
|
+
end
|
25
|
+
sleep 1 # wait to make sure env is replaced by sleep
|
20
26
|
end
|
21
27
|
|
22
28
|
def setup
|
23
|
-
@ptable = ProcTable.ps.
|
29
|
+
@ptable = ProcTable.ps.find{ |ptable| ptable.pid == @@pid }
|
24
30
|
end
|
25
31
|
|
26
32
|
def test_fields
|
@@ -32,32 +38,67 @@ class TC_ProcTable_Darwin < Test::Unit::TestCase
|
|
32
38
|
def test_pid
|
33
39
|
assert_respond_to(@ptable, :pid)
|
34
40
|
assert_kind_of(Fixnum, @ptable.pid)
|
41
|
+
assert_equal(@ptable.pid, @@pid)
|
35
42
|
end
|
36
43
|
|
37
44
|
def test_ppid
|
38
45
|
assert_respond_to(@ptable, :ppid)
|
39
46
|
assert_kind_of(Fixnum, @ptable.ppid)
|
47
|
+
assert_equal(Process.pid, @ptable.ppid)
|
40
48
|
end
|
41
49
|
|
42
50
|
def test_pgid
|
43
51
|
assert_respond_to(@ptable, :pgid)
|
44
52
|
assert_kind_of(Fixnum, @ptable.pgid)
|
53
|
+
assert_equal(Process.getpgrp, @ptable.pgid)
|
45
54
|
end
|
46
55
|
|
47
56
|
def test_ruid
|
48
57
|
assert_respond_to(@ptable, :ruid)
|
49
58
|
assert_kind_of(Fixnum, @ptable.ruid)
|
59
|
+
assert_equal(Process.uid, @ptable.ruid)
|
50
60
|
end
|
51
61
|
|
52
62
|
def test_rgid
|
53
63
|
assert_respond_to(@ptable, :rgid)
|
54
64
|
assert_kind_of(Fixnum, @ptable.rgid)
|
65
|
+
assert_equal(Process.gid, @ptable.rgid)
|
66
|
+
end
|
67
|
+
|
68
|
+
def test_euid
|
69
|
+
assert_respond_to(@ptable, :euid)
|
70
|
+
assert_kind_of(Fixnum, @ptable.euid)
|
71
|
+
assert_equal(Process.euid, @ptable.euid)
|
72
|
+
end
|
73
|
+
|
74
|
+
def test_egid
|
75
|
+
assert_respond_to(@ptable, :egid)
|
76
|
+
assert_kind_of(Fixnum, @ptable.egid)
|
77
|
+
assert_equal(Process.egid, @ptable.egid)
|
78
|
+
end
|
79
|
+
|
80
|
+
def test_groups
|
81
|
+
assert_respond_to(@ptable, :groups)
|
82
|
+
assert_kind_of(Array, @ptable.groups)
|
83
|
+
assert_equal(Process.groups, @ptable.groups)
|
84
|
+
end
|
85
|
+
|
86
|
+
def test_svuid
|
87
|
+
assert_respond_to(@ptable, :svuid)
|
88
|
+
assert_kind_of(Fixnum, @ptable.svuid)
|
89
|
+
assert_equal(Process.uid, @ptable.svuid) # not valid for all processes
|
90
|
+
end
|
91
|
+
|
92
|
+
def test_svgid
|
93
|
+
assert_respond_to(@ptable, :svgid)
|
94
|
+
assert_kind_of(Fixnum, @ptable.svgid)
|
95
|
+
assert_equal(Process.gid, @ptable.svgid) # not valid for all processes
|
55
96
|
end
|
56
97
|
|
57
98
|
def test_comm
|
58
99
|
assert_respond_to(@ptable, :comm)
|
59
100
|
assert_kind_of(String, @ptable.comm)
|
60
|
-
|
101
|
+
assert_equal('sleep', @ptable.comm)
|
61
102
|
end
|
62
103
|
|
63
104
|
def test_state
|
@@ -114,6 +155,19 @@ class TC_ProcTable_Darwin < Test::Unit::TestCase
|
|
114
155
|
def test_cmdline
|
115
156
|
assert_respond_to(@ptable, :cmdline)
|
116
157
|
assert_kind_of(String, @ptable.cmdline)
|
158
|
+
assert_equal('sleep 60', @ptable.cmdline)
|
159
|
+
end
|
160
|
+
|
161
|
+
def test_exe
|
162
|
+
assert_respond_to(@ptable, :exe)
|
163
|
+
assert_kind_of(String, @ptable.exe)
|
164
|
+
assert_equal(`which sleep`.chomp, @ptable.exe)
|
165
|
+
end
|
166
|
+
|
167
|
+
def test_environ
|
168
|
+
assert_respond_to(@ptable, :environ)
|
169
|
+
assert_kind_of(Hash, @ptable.environ)
|
170
|
+
assert_equal({'A' => 'B', 'Z' => ''}, @ptable.environ)
|
117
171
|
end
|
118
172
|
|
119
173
|
def test_starttime
|
@@ -207,5 +261,7 @@ class TC_ProcTable_Darwin < Test::Unit::TestCase
|
|
207
261
|
|
208
262
|
def self.shutdown
|
209
263
|
@@fields = nil
|
264
|
+
|
265
|
+
Process.kill('TERM', @@pid)
|
210
266
|
end
|
211
267
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
##############################################################################
|
2
|
+
# test_sys_top.rb
|
3
|
+
#
|
4
|
+
# Test suite for the sys-top library that is included with this distribution.
|
5
|
+
##############################################################################
|
6
|
+
require 'rubygems'
|
7
|
+
gem 'test-unit'
|
8
|
+
|
9
|
+
require 'test/unit'
|
10
|
+
require 'sys/top'
|
11
|
+
|
12
|
+
class TC_Top < Test::Unit::TestCase
|
13
|
+
include Sys
|
14
|
+
|
15
|
+
def test_version
|
16
|
+
assert_equal('1.0.4', Top::VERSION)
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_top_basic
|
20
|
+
assert_respond_to(Top, :top)
|
21
|
+
assert_nothing_raised{ Top.top }
|
22
|
+
assert_nothing_raised{ Top.top(5) }
|
23
|
+
assert_nothing_raised{ Top.top(5, 'cmdline') }
|
24
|
+
end
|
25
|
+
|
26
|
+
def test_top
|
27
|
+
assert_equal(10, Top.top.length)
|
28
|
+
assert_kind_of(Struct::ProcTableStruct, Top.top.first)
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_top_with_size
|
32
|
+
assert_equal(5, Top.top(5).length)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_top_with_size_and_sort_by_field
|
36
|
+
assert_equal(5, Top.top(5, :cmdline).length)
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_top_return_type
|
40
|
+
assert_kind_of(Array, Top.top)
|
41
|
+
end
|
42
|
+
|
43
|
+
def test_top_expected_errors
|
44
|
+
assert_raises(ArgumentError){ Top.top(1, 'foo', 2) }
|
45
|
+
end
|
46
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sys-proctable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.5
|
5
5
|
platform: universal-darwin
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-02-10 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: test-unit
|
@@ -68,6 +68,7 @@ files:
|
|
68
68
|
- sys-proctable.gemspec
|
69
69
|
- test/test_sys_proctable_all.rb
|
70
70
|
- test/test_sys_proctable_darwin.rb
|
71
|
+
- test/test_sys_top.rb
|
71
72
|
homepage: http://www.rubyforge.org/projects/sysutils
|
72
73
|
licenses:
|
73
74
|
- Artistic 2.0
|
@@ -88,10 +89,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
88
89
|
version: '0'
|
89
90
|
requirements: []
|
90
91
|
rubyforge_project: sysutils
|
91
|
-
rubygems_version: 2.
|
92
|
+
rubygems_version: 2.4.5
|
92
93
|
signing_key:
|
93
94
|
specification_version: 4
|
94
95
|
summary: An interface for providing process table information
|
95
96
|
test_files:
|
96
97
|
- test/test_sys_proctable_all.rb
|
97
98
|
- test/test_sys_proctable_darwin.rb
|
99
|
+
- test/test_sys_top.rb
|