sys-proctable 0.9.4-universal-darwin → 0.9.5-universal-darwin

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 11f52508143ac983c07b528b5622e940486a41f1
4
- data.tar.gz: 1a897f239ba90adf065767ee4a58d3a3d2578dbf
3
+ metadata.gz: 3b1cdd14b7384e61fcbaebc7cb065b44a9e93c45
4
+ data.tar.gz: 42ba4f461988cb3cddb6509e5e650e7acbf6cd02
5
5
  SHA512:
6
- metadata.gz: e3a8a5a456d03c9131dddb824159718832f77e3d41d21f344a5e3c2b41f002a165bf9a651b71f058aacb9edd795ba6a85fa29e9e5feaecb6fe25d2f5569a492a
7
- data.tar.gz: bfef4c48d0089ffea5b5200c8a16aeaa2ab83437dcb3d5e7b4eed360241877a7eebc7735a0e78882f3aaff5e87359ed761c72fa5283833c0e2a43657fb3204ca
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
@@ -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.4"
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
- const char* fields[] = {
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
- /* Convert previous '\0'. */
155
- *np = ' ';
149
+ /* Convert previous '\0'. */
150
+ *np = ' ';
156
151
  } else {
157
- /* *argv0len = cp - sp; */
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
- * Don't convert '\0' characters to ' '.
165
- * However, we needed to know that the
166
- * command name was terminated, which we
167
- * now know.
168
- */
169
- break;
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
- strcpy(cmdline, sp);
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
- int err;
210
- char state[8];
211
- struct kinfo_proc* procs;
212
- VALUE v_pid, v_tty_num, v_tty_dev, v_start_time;
213
- VALUE v_pstruct = Qnil;
214
- VALUE v_array = rb_ary_new();
215
- size_t length, count;
216
- size_t i = 0;
217
- char args[ARGS_MAX_LEN+1];
218
-
219
- // Passed into sysctl call
220
- static const int name_mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0};
221
-
222
- rb_scan_args(argc, argv, "01", &v_pid);
223
-
224
- // Get size of proc kproc buffer
225
- err = sysctl( (int *) name_mib, PROC_MIB_LEN, NULL, &length, NULL, 0);
226
-
227
- if(err == -1)
228
- rb_raise(cProcTableError, "sysctl: %s", strerror(errno));
229
-
230
- // Populate the kproc buffer
231
- procs = malloc(length);
232
-
233
- if(procs == NULL)
234
- rb_raise(cProcTableError, "malloc: %s", strerror(errno));
235
-
236
- err = sysctl( (int *) name_mib, PROC_MIB_LEN, procs, &length, NULL, 0);
237
-
238
- if(err == -1)
239
- rb_raise(cProcTableError, "sysctl: %s", strerror(errno));
240
-
241
- // If we're here, we got our list
242
- count = length / sizeof(struct kinfo_proc);
243
-
244
- for(i = 0; i < count; i++) {
245
- v_tty_num = Qnil;
246
- v_tty_dev = Qnil;
247
- v_start_time = Qnil;
248
-
249
- // If a PID is provided, skip unless the PID matches
250
- if( (!NIL_P(v_pid)) && (procs[i].kp_proc.p_pid != NUM2INT(v_pid)) )
251
- continue;
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
- *args = '\0';
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
- /* Query the command line args */
256
- /* TODO: Cmd line not working for now - fix */
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
- /*args_mib[ARGS_MIB_LEN - 1] = procs[i].kp_proc.p_pid;
259
- args_err = sysctl( (int *) args_mib, ARGS_MIB_LEN, args, &args_size, NULL, 0);
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
- if(args_err >= 0) {
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
- // Get ttynum and ttydev. If ttynum is -1, there is no tty.
305
- if(procs[i].kp_eproc.e_tdev != -1){
306
- v_tty_num = INT2FIX(procs[i].kp_eproc.e_tdev),
307
- v_tty_dev = rb_str_new2(devname(procs[i].kp_eproc.e_tdev, S_IFCHR));
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
- v_pstruct = rb_struct_new(
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
- VALUE v_array = rb_ary_new();
378
- int size = sizeof(fields) / sizeof(fields[0]);
379
- int i;
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
- for(i = 0; i < size; i++)
382
- rb_ary_push(v_array, rb_str_new2(fields[i]));
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
- return v_array;
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
- VALUE mSys, cProcTable;
392
-
393
- /* The Sys module serves as a namespace only */
394
- mSys = rb_define_module("Sys");
395
-
396
- /* The ProcTable class encapsulates process table information */
397
- cProcTable = rb_define_class_under(mSys, "ProcTable", rb_cObject);
398
-
399
- /* The Error class typically raised if any of the ProcTable methods fail */
400
- cProcTableError = rb_define_class_under(cProcTable, "Error", rb_eStandardError);
401
-
402
- /* Singleton methods */
403
-
404
- rb_define_singleton_method(cProcTable, "ps", pt_ps, -1);
405
- rb_define_singleton_method(cProcTable, "fields", pt_fields, 0);
406
-
407
- /* There is no constructor */
408
- rb_funcall(cProcTable, rb_intern("private_class_method"), 1, ID2SYM(rb_intern("new")));
409
-
410
- /* Constants */
411
-
412
- /* 0.9.3: The version of the sys-proctable library */
413
- rb_define_const(cProcTable, "VERSION", rb_str_new2(SYS_PROCTABLE_VERSION));
414
-
415
- /* Structs */
416
-
417
- sProcStruct = rb_struct_define("ProcTableStruct","pid","ppid","pgid","ruid",
418
- "rgid","comm","state","pctcpu","oncpu","tnum","tdev","wmesg",
419
- "rtime", "priority","usrpri","nice","cmdline","starttime",
420
- "maxrss","ixrss","idrss","isrss","minflt","majflt","nswap",
421
- "inblock","oublock","msgsnd","msgrcv","nsignals","nvcsw","nivcsw",
422
- "utime","stime", NULL
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
-
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'sys-proctable'
5
- spec.version = '0.9.4'
5
+ spec.version = '0.9.5'
6
6
  spec.author = 'Daniel J. Berger'
7
7
  spec.license = 'Artistic 2.0'
8
8
  spec.email = 'djberg96@gmail.com'
@@ -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.4', ProcTable::VERSION)
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 comm state pctcpu oncpu tnum
16
- tdev wmesg rtime priority usrpri nice cmdline starttime
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.last
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
- assert_true(@ptable.comm.length > 0)
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
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: 2014-03-04 00:00:00.000000000 Z
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.2.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