~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/daemons/common/procfs.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*___INFO__MARK_BEGIN__*/
 
2
/*************************************************************************
 
3
 * 
 
4
 *  The Contents of this file are made available subject to the terms of
 
5
 *  the Sun Industry Standards Source License Version 1.2
 
6
 * 
 
7
 *  Sun Microsystems Inc., March, 2001
 
8
 * 
 
9
 * 
 
10
 *  Sun Industry Standards Source License Version 1.2
 
11
 *  =================================================
 
12
 *  The contents of this file are subject to the Sun Industry Standards
 
13
 *  Source License Version 1.2 (the "License"); You may not use this file
 
14
 *  except in compliance with the License. You may obtain a copy of the
 
15
 *  License at http://gridengine.sunsource.net/Gridengine_SISSL_license.html
 
16
 * 
 
17
 *  Software provided under this License is provided on an "AS IS" basis,
 
18
 *  WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING,
 
19
 *  WITHOUT LIMITATION, WARRANTIES THAT THE SOFTWARE IS FREE OF DEFECTS,
 
20
 *  MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE, OR NON-INFRINGING.
 
21
 *  See the License for the specific provisions governing your rights and
 
22
 *  obligations concerning the Software.
 
23
 * 
 
24
 *   The Initial Developer of the Original Code is: Sun Microsystems, Inc.
 
25
 * 
 
26
 *   Copyright: 2001 by Sun Microsystems, Inc.
 
27
 * 
 
28
 *   All Rights Reserved.
 
29
 * 
 
30
 ************************************************************************/
 
31
/*___INFO__MARK_END__*/
 
32
#if !defined(COMPILE_DC)
 
33
 
 
34
int verydummyprocfs;
 
35
 
 
36
#else
 
37
 
 
38
#include <stdio.h>
 
39
#include <fcntl.h>
 
40
#include <time.h>
 
41
#include <errno.h>
 
42
#include <sys/ioctl.h>
 
43
#include <sys/types.h>
 
44
#include <sys/signal.h>
 
45
 
 
46
#if !defined(CRAY) && !defined(NECSX4) && !defined(NECSX5) && !defined(AIX)
 
47
#include <sys/syscall.h>
 
48
#endif
 
49
 
 
50
#include <unistd.h>
 
51
#include <sys/times.h>
 
52
#include <sys/wait.h>
 
53
#if defined(FREEBSD) || defined(DARWIN)
 
54
#include <sys/time.h>
 
55
#endif
 
56
#include <sys/resource.h>
 
57
#include <dirent.h>
 
58
#include <stdlib.h>
 
59
#include <string.h>
 
60
#include <signal.h>
 
61
 
 
62
#if defined(ALPHA) 
 
63
#  include <sys/user.h>
 
64
#  include <sys/table.h>   
 
65
#  include <sys/procfs.h>   
 
66
#endif
 
67
 
 
68
#if defined(SOLARIS) 
 
69
#  include <sys/procfs.h>   
 
70
#endif
 
71
 
 
72
#if defined(LINUX)
 
73
#include <sys/param.h>          /* for HZ (jiffies -> seconds ) */
 
74
#endif
 
75
 
 
76
#include "uti/sge_stdio.h"
 
77
#include "uti/sge_unistd.h"
 
78
 
 
79
#include "sge_log.h"
 
80
#include "msg_sge.h"
 
81
#include "sgermon.h"
 
82
#include "basis_types.h"
 
83
#include "sgedefs.h"
 
84
#include "exec_ifm.h"
 
85
#include "pdc.h"
 
86
 
 
87
#if !defined(CRAY)
 
88
#include "procfs.h"
 
89
#endif
 
90
 
 
91
#if defined(LINUX) || defined(ALPHA) || defined(SOLARIS)
 
92
#   if defined(SVR3)
 
93
#      define PROC_DIR "/debug"
 
94
#   else
 
95
#      define PROC_DIR "/proc"
 
96
#   endif
 
97
#endif
 
98
 
 
99
#if defined(LINUX)
 
100
 
 
101
#define BIGLINE 1024
 
102
 
 
103
typedef struct _tLinProcStat {     /* process Linux /proc/pid/stat structure */
 
104
   int   pr_pid;                  /*  1 process id */
 
105
   char  pr_cmd[16];              /*  2 command name */
 
106
   char  pr_stat;                 /*  3 process status */
 
107
   int   pr_ppid;                 /*  4 parent process id */
 
108
   int   pr_pgrp;                 /*  5 process group */
 
109
   int   pr_sid;                  /*  6 session id */
 
110
   int   pr_tty;                  /*  7 tty line MAJOR << ? + MINOR */
 
111
   int   pr_tty_pgrp;             /*  8 tty process group */
 
112
   long  pr_flags;                /*  9 process flags PF_* in <linux/sched.h> */
 
113
   long  pr_min_flt;              /* 10 minor page faults */
 
114
   long  pr_cmin_flt;             /* 11 children minor page faults */
 
115
   long  pr_maj_flt;              /* 12 major page faults */
 
116
   long  pr_cmaj_flt;             /* 13 children major page faults */
 
117
   long  pr_utime;                /* 14 user time */
 
118
   long  pr_stime;                /* 15 system time */
 
119
   long  pr_cutime;               /* 16 children user time */
 
120
   long  pr_cstime;               /* 17 children system time */
 
121
   long  pr_counter;                    /* 18 jiffies */
 
122
   long  pr_pri;                  /* 19 priority (nice) */
 
123
   long  pr_tmout;                /* 20 Timeout time for scheduling */
 
124
   long  pr_it_real_value;        /* 21 itimer real value */
 
125
   long  pr_start;                /* 22 start of execution in jiffies since boot*/
 
126
   long  pr_vsize;                /* 23 total size t + d + s NOT pages */
 
127
   long  pr_rss;                  /* 24 resident set size pages */
 
128
   long  pr_rlim_cur;             /* 25 current rlimit ro rss */
 
129
   long  pr_start_code;           /* 26 start of code */
 
130
   long  pr_end_code;             /* 27 end of code */
 
131
   long  pr_start_stack;          /* 28 start of stack */
 
132
   long  pr_esp;                  /* 29 head of stack (stack pointer) */
 
133
   long  pr_eip;                  /* 30 instruction pointer */
 
134
   long  pr_signal;               /* 31 pending signals mask */
 
135
   long  pr_blocked;              /* 32 blocked signals mask */
 
136
   long  pr_sigignore;            /* 33 ignored signals mask */
 
137
   long  pr_sigcatch;             /* 34 catched signals mask */
 
138
   long  pr_wchan;                /* 35 WCHAN (seems to be a return address) */
 
139
} tLinProcStat;
 
140
#endif
 
141
 
 
142
 
 
143
/*-----------------------------------------------------------------------*/
 
144
#if defined(LINUX) || defined(ALPHA) || defined(SOLARIS)
 
145
 
 
146
static DIR *cwd;
 
147
static struct dirent *dent;
 
148
 
 
149
#if defined(LINUX)
 
150
 
 
151
int groups_in_proc (void) 
 
152
{
 
153
   char buf[1024];
 
154
   FILE* fd = (FILE*) NULL;
 
155
   
 
156
   if (!(fd = fopen(PROC_DIR "/self/status", "r"))) {
 
157
      return 0;
 
158
   }
 
159
   while (fgets(buf, sizeof(buf), fd)) {
 
160
      if (strcmp("Groups:", strtok(buf, "\t"))==0) {
 
161
         FCLOSE(fd);
 
162
         return 1;
 
163
      }
 
164
   }
 
165
   FCLOSE(fd);
 
166
   return 0;
 
167
FCLOSE_ERROR:
 
168
   return 0;
 
169
}
 
170
 
 
171
#endif
 
172
 
 
173
 
 
174
/* search in job list for the pid
 
175
   return the proc element */
 
176
static lnk_link_t *find_pid_in_jobs(pid_t pid, lnk_link_t *job_list)
 
177
{
 
178
   lnk_link_t *job, *proc = NULL;
 
179
   proc_elem_t *proc_elem = NULL;
 
180
   job_elem_t *job_elem = NULL;
 
181
 
 
182
   /*
 
183
    * try to find a matching job
 
184
    */
 
185
   for (job=job_list->next; job != job_list; job=job->next) {
 
186
 
 
187
      job_elem = LNK_DATA(job, job_elem_t, link);
 
188
 
 
189
      /*
 
190
       * try to find process in this jobs' proc list
 
191
       */
 
192
 
 
193
      for (proc=job_elem->procs.next; proc != &job_elem->procs;
 
194
               proc=proc->next) {
 
195
 
 
196
         proc_elem = LNK_DATA(proc, proc_elem_t, link);
 
197
         if (proc_elem->proc.pd_pid == pid)
 
198
            break; /* found it */
 
199
      }
 
200
 
 
201
      if (proc == &job_elem->procs) {
 
202
         /* end of procs list - no process found - try next job */
 
203
         proc = NULL;
 
204
      } else
 
205
         /* found a process */
 
206
         break;
 
207
   }
 
208
 
 
209
   return proc;
 
210
}
 
211
 
 
212
 
 
213
static void touch_time_stamp(const char *d_name, int time_stamp, lnk_link_t *job_list)
 
214
{
 
215
   pid_t pid;
 
216
   proc_elem_t *proc_elem;
 
217
   lnk_link_t *proc;
 
218
 
 
219
   DENTER(TOP_LAYER, "touch_time_stamp");
 
220
 
 
221
   sscanf(d_name, pid_t_fmt, &pid);
 
222
   if ((proc = find_pid_in_jobs(pid, job_list))) {
 
223
      proc_elem = LNK_DATA(proc, proc_elem_t, link);
 
224
      proc_elem->proc.pd_tstamp = time_stamp;
 
225
#ifdef MONITOR_PDC
 
226
      INFO((SGE_EVENT, "found job to process %s: set time stamp\n", d_name));
 
227
#endif
 
228
   }
 
229
#ifdef MONITOR_PDC
 
230
   else
 
231
      INFO((SGE_EVENT, "found no job to process %s\n", d_name));
 
232
#endif
 
233
 
 
234
   DEXIT;
 
235
   return;
 
236
}
 
237
 
 
238
void procfs_kill_addgrpid(gid_t add_grp_id, int sig,
 
239
   tShepherd_trace shepherd_trace)
 
240
{
 
241
   char procnam[128];
 
242
   int i;
 
243
   int groups=0;
 
244
   u_long32 max_groups;
 
245
   gid_t *list;
 
246
#if defined(SOLARIS) || defined(ALPHA)
 
247
   int fd;
 
248
   prcred_t proc_cred;
 
249
#elif defined(LINUX)
 
250
   FILE *fp;
 
251
   char buffer[1024];
 
252
   uid_t uids[4];
 
253
   gid_t gids[4];
 
254
#endif
 
255
 
 
256
   DENTER(TOP_LAYER, "procfs_kill_addgrpid");
 
257
 
 
258
   /* quick return in case of invalid add. group id */
 
259
   if (add_grp_id == 0) {
 
260
      DEXIT;
 
261
      return;
 
262
   }
 
263
 
 
264
   max_groups = sge_sysconf(SGE_SYSCONF_NGROUPS_MAX);
 
265
   if (max_groups <= 0)
 
266
      if (shepherd_trace) {
 
267
         char err_str[256];
 
268
 
 
269
         sprintf(err_str, MSG_SGE_NGROUPS_MAXOSRECONFIGURATIONNECESSARY );
 
270
         shepherd_trace(err_str);
 
271
      }
 
272
/*
 
273
 * INSURE detects a WRITE_OVERFLOW when getgroups was invoked (LINUX).
 
274
 * Is this a bug in the kernel or in INSURE?
 
275
 */
 
276
#if defined(LINUX)
 
277
   list = (gid_t*) malloc(2*max_groups*sizeof(gid_t));
 
278
#else
 
279
   list = (gid_t*) malloc(max_groups*sizeof(gid_t));
 
280
#endif
 
281
   if (list == NULL)
 
282
      if (shepherd_trace) {
 
283
         char err_str[256];
 
284
 
 
285
         sprintf(err_str, MSG_SGE_PROCFSKILLADDGRPIDMALLOCFAILED );
 
286
         shepherd_trace(err_str);
 
287
      }
 
288
 
 
289
   pt_open();
 
290
 
 
291
   /* find next valid entry in procfs  */
 
292
   while ((dent = readdir(cwd))) {
 
293
      if (!dent->d_name)
 
294
         continue;
 
295
      if (!dent->d_name[0])
 
296
         continue;
 
297
 
 
298
      if (!strcmp(dent->d_name, "..") || !strcmp(dent->d_name, "."))
 
299
         continue;
 
300
 
 
301
      if (atoi(dent->d_name) == 0)
 
302
         continue;
 
303
 
 
304
#if defined(SOLARIS) || defined(ALPHA)
 
305
      sprintf(procnam, "%s/%s", PROC_DIR, dent->d_name);
 
306
      if ((fd = open(procnam, O_RDONLY, 0)) == -1) {
 
307
         DPRINTF(("open(%s) failed: %s\n", procnam, strerror(errno)));
 
308
         continue;
 
309
      }
 
310
#elif defined(LINUX)
 
311
      if (!strcmp(dent->d_name, "self"))
 
312
         continue;
 
313
 
 
314
      sprintf(procnam, "%s/%s/status", PROC_DIR, dent->d_name);
 
315
      if (!(fp = fopen(procnam, "r")))
 
316
         continue;
 
317
#endif
 
318
 
 
319
#if defined(SOLARIS) || defined(ALPHA)
 
320
      /* get number of groups */
 
321
      if (ioctl(fd, PIOCCRED, &proc_cred) == -1) {
 
322
         close(fd);
 
323
         continue;
 
324
      }
 
325
 
 
326
      /* get list of supplementary groups */
 
327
      groups = proc_cred.pr_ngroups;
 
328
      if (ioctl(fd, PIOCGROUPS, list) == -1) {
 
329
         close(fd);
 
330
         continue;
 
331
      }
 
332
 
 
333
#elif defined(LINUX)
 
334
      /* get number of groups and current uids, gids
 
335
       * uids[0], gids[0] => UID and GID
 
336
       * uids[1], gids[1] => EUID and EGID
 
337
       * uids[2], gids[2] => SUID and SGID
 
338
       * uids[3], gids[3] => FSUID and FSGID
 
339
       */
 
340
      groups = 0;
 
341
      while (fgets(buffer, sizeof(buffer), fp)) {
 
342
         char *label = NULL;
 
343
         char *token = NULL;
 
344
 
 
345
         label = strtok(buffer, " \t\n");
 
346
         if (label) {
 
347
            if (!strcmp("Groups:", label)) {
 
348
               while ((token = strtok((char*) NULL, " \t\n"))) {
 
349
                  list[groups]=(gid_t) atol(token);
 
350
                  groups++;
 
351
               }
 
352
            } else if (!strcmp("Uid:", label)) {
 
353
               int i = 0;
 
354
 
 
355
               while ((i < 4) && (token = strtok((char*) NULL, " \t\n"))) {
 
356
                  uids[i]=(uid_t) atol(token);
 
357
                  i++;
 
358
               }
 
359
            } else if (!strcmp("Gid:", label)) {
 
360
               int i = 0;
 
361
 
 
362
               while ((i < 4) && (token = strtok((char*) NULL, " \t\n"))) {
 
363
                  gids[i]=(gid_t) atol(token);
 
364
                  i++;
 
365
               }
 
366
            }
 
367
         }
 
368
      }
 
369
#endif
 
370
 
 
371
#if defined(SOLARIS) || defined(ALPHA)
 
372
      close(fd);
 
373
#elif defined(LINUX)
 
374
      FCLOSE(fp);
 
375
FCLOSE_ERROR:
 
376
#endif
 
377
 
 
378
      /* send each process a signal which belongs to add_grg_id */
 
379
      for (i = 0; i < groups; i++) {
 
380
         if (list[i] == add_grp_id) {
 
381
            pid_t pid;
 
382
            pid = (pid_t) atol(dent->d_name);
 
383
 
 
384
#if defined(LINUX)
 
385
            /* if UID, GID, EUID and EGID == 0
 
386
             *  don't kill the process!!! - it could be the rpc.nfs-deamon
 
387
             */
 
388
            if (!(uids[0] == 0 && gids[0] == 0 &&
 
389
                  uids[1] == 0 && gids[1] == 0)) {
 
390
#elif defined(SOLARIS) || defined(ALPHA)
 
391
            if (!(proc_cred.pr_ruid == 0 && proc_cred.pr_rgid == 0 &&
 
392
                  proc_cred.pr_euid == 0 && proc_cred.pr_egid == 0)) {
 
393
#endif
 
394
 
 
395
               if (shepherd_trace) {
 
396
                  char err_str[256];
 
397
 
 
398
                  sprintf(err_str, MSG_SGE_KILLINGPIDXY_UI , sge_u32c(pid), groups);
 
399
                  shepherd_trace(err_str);
 
400
               }
 
401
 
 
402
               kill(pid, sig);
 
403
 
 
404
            } else {
 
405
               if (shepherd_trace) {
 
406
                  char err_str[256];
 
407
 
 
408
                  sprintf(err_str, MSG_SGE_DONOTKILLROOTPROCESSXY_UI ,
 
409
                     sge_u32c(atol(dent->d_name)), groups);
 
410
                  shepherd_trace(err_str);
 
411
               }
 
412
            }
 
413
 
 
414
            break;
 
415
         }
 
416
      }
 
417
   }
 
418
   pt_close();
 
419
   free(list);
 
420
   DEXIT;
 
421
}
 
422
 
 
423
int pt_open(void)
 
424
{
 
425
   cwd = opendir(PROC_DIR);
 
426
   return !cwd;
 
427
}
 
428
void pt_close(void)
 
429
{
 
430
   closedir(cwd);
 
431
}
 
432
 
 
433
int pt_dispatch_proc_to_job(
 
434
lnk_link_t *job_list,
 
435
int time_stamp 
 
436
) {
 
437
   char procnam[128];
 
438
   int fd = -1;
 
439
#if defined(LINUX)
 
440
   char buffer[BIGLINE];
 
441
   tLinProcStat pr;
 
442
   SGE_STRUCT_STAT fst;
 
443
#else
 
444
   prstatus_t pr;
 
445
   prpsinfo_t pri;
 
446
#endif
 
447
 
 
448
#if defined(SOLARIS) || defined(ALPHA)   
 
449
   prcred_t proc_cred;
 
450
#endif
 
451
 
 
452
   int ret;
 
453
   u_long32 max_groups;
 
454
   gid_t *list;
 
455
   int groups=0;
 
456
 
 
457
   proc_elem_t *proc_elem = NULL;
 
458
   job_elem_t *job_elem = NULL;
 
459
   lnk_link_t *curr;
 
460
   double old_time = 0;
 
461
   uint64 old_vmem = 0;
 
462
 
 
463
   DENTER(TOP_LAYER, "pt_dispatch_proc_to_job");
 
464
 
 
465
   max_groups = sge_sysconf(SGE_SYSCONF_NGROUPS_MAX);
 
466
   if (max_groups <= 0) {
 
467
      ERROR((SGE_EVENT, MSG_SGE_NGROUPS_MAXOSRECONFIGURATIONNECESSARY));
 
468
      DEXIT;
 
469
      return 1;  
 
470
   }   
 
471
 
 
472
   list = (gid_t*) malloc(max_groups*sizeof(gid_t));
 
473
   if (list == NULL) {
 
474
      ERROR((SGE_EVENT, MSG_SGE_PTDISPATCHPROCTOJOBMALLOCFAILED));
 
475
      DEXIT;
 
476
      return 1;
 
477
   }
 
478
 
 
479
   /* find next valid entry in procfs */ 
 
480
   while ((dent = readdir(cwd))) {
 
481
      char *pidname;
 
482
 
 
483
      if (!dent->d_name)
 
484
         continue;
 
485
      if (!dent->d_name[0])
 
486
         continue;
 
487
 
 
488
      if (!strcmp(dent->d_name, "..") || !strcmp(dent->d_name, "."))
 
489
         continue;
 
490
 
 
491
      if (dent->d_name[0] == '.')
 
492
          pidname = &dent->d_name[1];
 
493
      else
 
494
          pidname = dent->d_name;
 
495
 
 
496
      if (atoi(pidname) == 0)
 
497
         continue;
 
498
 
 
499
#if defined(LINUX)
 
500
      sprintf(procnam, "%s/%s/stat", PROC_DIR, dent->d_name);
 
501
#else
 
502
      sprintf(procnam, "%s/%s", PROC_DIR, dent->d_name);
 
503
#endif
 
504
      if ((fd = open(procnam, O_RDONLY, 0)) == -1) {
 
505
         if (errno != ENOENT) {
 
506
#ifdef MONITOR_PDC
 
507
            if (errno == EACCES)
 
508
               INFO((SGE_EVENT, "(uid:"gid_t_fmt" euid:"gid_t_fmt") could not open %s: %s\n",
 
509
                        getuid(), geteuid(), procnam, strerror(errno)));
 
510
            else
 
511
               INFO((SGE_EVENT, "could not open %s: %s\n", procnam, strerror(errno)));
 
512
#endif
 
513
            touch_time_stamp(dent->d_name, time_stamp, job_list);
 
514
         }
 
515
         continue;
 
516
      }
 
517
 
 
518
      /** 
 
519
       ** get a list of supplementary group ids to decide
 
520
       ** whether this process will be needed;
 
521
       ** read also prstatus
 
522
       **/
 
523
 
 
524
#  if defined(LINUX)
 
525
 
 
526
      /* 
 
527
       * Read the line and append a 0-Byte 
 
528
       */
 
529
      if ((ret = read(fd, buffer, BIGLINE-1))<=0) {
 
530
         close(fd);
 
531
         if (ret == -1 && errno != ENOENT) {
 
532
#ifdef MONITOR_PDC
 
533
            INFO((SGE_EVENT, "could not read %s: %s\n", procnam, strerror(errno)));
 
534
#endif
 
535
            touch_time_stamp(dent->d_name, time_stamp, job_list);
 
536
         }
 
537
         continue;
 
538
      }
 
539
      buffer[BIGLINE-1] = '\0';
 
540
      
 
541
      if (SGE_FSTAT(fd, &fst)) {
 
542
         close(fd);
 
543
         if (errno != ENOENT) {
 
544
#ifdef MONITOR_PDC
 
545
            INFO((SGE_EVENT, "could not fstat %s: %s\n", procnam, strerror(errno)));
 
546
#endif
 
547
            touch_time_stamp(dent->d_name, time_stamp, job_list);
 
548
         }
 
549
         continue;
 
550
      }
 
551
 
 
552
      /* 
 
553
       * get prstatus
 
554
       */
 
555
      ret = sscanf(buffer, 
 
556
                   "%d %s %c %d %d %d %d %d %lu %lu \
 
557
                    %lu %lu %lu %ld %ld %ld %ld %ld %ld %lu \
 
558
                    %lu %ld %lu %lu %lu %lu %lu %lu %lu %lu \
 
559
                    %lu %lu %lu %lu %lu",
 
560
                    &pr.pr_pid,
 
561
                    pr.pr_cmd, 
 
562
                    &pr.pr_stat,
 
563
                    &pr.pr_ppid,
 
564
                    &pr.pr_pgrp,
 
565
                    &pr.pr_sid,
 
566
                    &pr.pr_tty,
 
567
                    &pr.pr_tty_pgrp,
 
568
                    &pr.pr_flags,   
 
569
                    &pr.pr_min_flt, 
 
570
                    &pr.pr_cmin_flt,
 
571
                    &pr.pr_maj_flt, 
 
572
                    &pr.pr_cmaj_flt,
 
573
                    &pr.pr_utime,   
 
574
                    &pr.pr_stime,   
 
575
                    &pr.pr_cutime,  
 
576
                    &pr.pr_cstime,
 
577
                    &pr.pr_counter,  
 
578
                    &pr.pr_pri,     
 
579
                    &pr.pr_tmout,   
 
580
                    &pr.pr_it_real_value,
 
581
                    &pr.pr_start,
 
582
                    &pr.pr_vsize,
 
583
                    &pr.pr_rss,  
 
584
                    &pr.pr_rlim_cur,
 
585
                    &pr.pr_start_code,
 
586
                    &pr.pr_end_code,  
 
587
                    &pr.pr_start_stack,
 
588
                    &pr.pr_esp,
 
589
                    &pr.pr_eip,
 
590
                    &pr.pr_signal,
 
591
                    &pr.pr_blocked,
 
592
                    &pr.pr_sigignore,
 
593
                    &pr.pr_sigcatch, 
 
594
                    &pr.pr_wchan);   
 
595
 
 
596
      if (ret != 35) {
 
597
         close(fd);
 
598
         continue;
 
599
      }
 
600
 
 
601
      /* 
 
602
       * get number of groups; 
 
603
       * get list of supplementary groups 
 
604
       */
 
605
      {
 
606
         char procnam[256];
 
607
         char buf[1024];
 
608
         FILE* f = (FILE*) NULL;
 
609
   
 
610
         sprintf(procnam,  "%s/%s/status", PROC_DIR, dent->d_name);
 
611
         if (!(f = fopen(procnam, "r"))) {
 
612
            close(fd);
 
613
            continue;
 
614
         }
 
615
         groups = 0;
 
616
         while (fgets(buf, sizeof(buf), f)) {
 
617
            if (strcmp("Groups:", strtok(buf, "\t"))==0) {
 
618
               char *token;
 
619
                  
 
620
               while ((token=strtok((char*) NULL, " "))) {
 
621
                  list[groups]=atol(token);
 
622
                  groups++;
 
623
               }
 
624
               break;
 
625
            }
 
626
         }
 
627
         FCLOSE(f);
 
628
FCLOSE_ERROR:
 
629
         ;
 
630
      } 
 
631
#  elif defined(SOLARIS) || defined(ALPHA)
 
632
      
 
633
      /* 
 
634
       * get prstatus 
 
635
       */
 
636
      if (ioctl(fd, PIOCSTATUS, &pr)==-1) {
 
637
         close(fd);
 
638
         if (errno != ENOENT) {
 
639
#ifdef MONITOR_PDC
 
640
            INFO((SGE_EVENT, "could not ioctl(PIOCSTATUS) %s: %s\n", procnam, strerror(errno)));
 
641
#endif
 
642
            touch_time_stamp(dent->d_name, time_stamp, job_list);
 
643
         }
 
644
         continue;
 
645
      }
 
646
                                    
 
647
      /* 
 
648
       * get number of groups 
 
649
       */
 
650
      ret=ioctl(fd, PIOCCRED, &proc_cred);
 
651
      if (ret < 0) {
 
652
         close(fd);
 
653
         if (errno != ENOENT) {
 
654
#ifdef MONITOR_PDC
 
655
            INFO((SGE_EVENT, "could not ioctl(PIOCCRED) %s: %s\n", procnam, strerror(errno)));
 
656
#endif
 
657
            touch_time_stamp(dent->d_name, time_stamp, job_list);
 
658
         }
 
659
         continue;
 
660
      }
 
661
      
 
662
      /* 
 
663
       * get list of supplementary groups 
 
664
       */
 
665
      groups = proc_cred.pr_ngroups;
 
666
      ret=ioctl(fd, PIOCGROUPS, list);
 
667
      if (ret<0) {
 
668
         close(fd);
 
669
         if (errno != ENOENT) {
 
670
#ifdef MONITOR_PDC
 
671
            INFO((SGE_EVENT, "could not ioctl(PIOCCRED) %s: %s\n", procnam, strerror(errno)));
 
672
#endif
 
673
            touch_time_stamp(dent->d_name, time_stamp, job_list);
 
674
         }
 
675
         continue;
 
676
      }
 
677
 
 
678
#  endif
 
679
 
 
680
      /* 
 
681
       * try to find a matching job 
 
682
       */
 
683
      for (curr=job_list->next; curr != job_list; curr=curr->next) {
 
684
         int found_it = 0;
 
685
         int group;
 
686
         
 
687
         job_elem = LNK_DATA(curr, job_elem_t, link);
 
688
         for (group=0; !found_it && group<groups; group++) {
 
689
            if (job_elem->job.jd_jid == list[group]) {
 
690
               found_it = 1;
 
691
            }
 
692
         }
 
693
         if (found_it)
 
694
            break;
 
695
      }
 
696
 
 
697
      if (curr == job_list) { /* this is not a traced process */ 
 
698
         close(fd);
 
699
         continue;
 
700
      }
 
701
 
 
702
      /* we always read only one entry per function call
 
703
         the while loop is needed to read next one */
 
704
      break;
 
705
   } /* while */
 
706
 
 
707
   free(list);
 
708
 
 
709
   if (!dent) {/* visited all files in procfs */
 
710
      DEXIT;
 
711
      return 1;
 
712
   }
 
713
   /* 
 
714
    * try to find process in this jobs' proc list 
 
715
    */
 
716
 
 
717
   for (curr=job_elem->procs.next; curr != &job_elem->procs; 
 
718
            curr=curr->next) {
 
719
      proc_elem = LNK_DATA(curr, proc_elem_t, link);
 
720
      
 
721
      if (proc_elem->proc.pd_pid == pr.pr_pid)
 
722
         break;
 
723
   }
 
724
 
 
725
   if (curr == &job_elem->procs) { 
 
726
      /* new process, add a proc element into jobs proc list */
 
727
      if (!(proc_elem=(proc_elem_t *)malloc(sizeof(proc_elem_t)))) {
 
728
         if (fd >= 0)
 
729
            close(fd);
 
730
         DEXIT;
 
731
         return 0;
 
732
      }
 
733
      memset(proc_elem, 0, sizeof(proc_elem_t));
 
734
      proc_elem->proc.pd_length = sizeof(psProc_t);
 
735
      proc_elem->proc.pd_state  = 1; /* active */
 
736
      LNK_ADD(job_elem->procs.prev, &proc_elem->link);
 
737
      job_elem->job.jd_proccount++;
 
738
 
 
739
#ifdef MONITOR_PDC
 
740
      {
 
741
         double utime, stime;
 
742
#if defined(LINUX)
 
743
         utime = ((double)pr.pr_utime)/HZ; 
 
744
         stime = ((double)pr.pr_stime)/HZ;
 
745
#else
 
746
         utime = pr.pr_utime.tv_sec + pr.pr_utime.tv_nsec*1E-9;
 
747
         stime = pr.pr_stime.tv_sec + pr.pr_stime.tv_nsec*1E-9;
 
748
#endif
 
749
         INFO((SGE_EVENT, "new process "pid_t_fmt" for job "pid_t_fmt" (utime = %f stime = %f)\n", 
 
750
               pr.pr_pid, job_elem->job.jd_jid, utime, stime)); 
 
751
      }
 
752
#endif
 
753
 
 
754
   } else {
 
755
      /* save previous usage data - needed to build delta usage */
 
756
      old_time = proc_elem->proc.pd_utime + proc_elem->proc.pd_stime;
 
757
      old_vmem  = proc_elem->vmem;
 
758
   }
 
759
 
 
760
   proc_elem->proc.pd_tstamp = time_stamp;
 
761
 
 
762
   proc_elem->proc.pd_pid    = pr.pr_pid;
 
763
#if defined(LINUX)
 
764
   proc_elem->proc.pd_utime  = ((double)pr.pr_utime)/HZ;
 
765
   proc_elem->proc.pd_stime  = ((double)pr.pr_stime)/HZ;
 
766
   /* could retrieve uid/gid using stat() on stat file */
 
767
   proc_elem->vmem           = pr.pr_vsize;
 
768
#else
 
769
   proc_elem->proc.pd_utime  = pr.pr_utime.tv_sec + pr.pr_utime.tv_nsec*1E-9;
 
770
   proc_elem->proc.pd_stime  = pr.pr_stime.tv_sec + pr.pr_stime.tv_nsec*1E-9;
 
771
    
 
772
   /* Don't care if this part fails */
 
773
   if (ioctl(fd, PIOCPSINFO, &pri) != -1) {
 
774
      proc_elem->proc.pd_uid    = pri.pr_uid;
 
775
      proc_elem->proc.pd_gid    = pri.pr_gid;
 
776
      proc_elem->vmem           = pri.pr_size * pagesize;
 
777
      proc_elem->rss            = pri.pr_rssize * pagesize;
 
778
      proc_elem->proc.pd_pstart = pri.pr_start.tv_sec + pri.pr_start.tv_nsec*1E-9;
 
779
   }
 
780
#endif         
 
781
 
 
782
   proc_elem->mem = 
 
783
         ((proc_elem->proc.pd_stime + proc_elem->proc.pd_utime) - old_time) * 
 
784
         (( old_vmem + proc_elem->vmem)/2);
 
785
 
 
786
#if defined(ALPHA)
 
787
#define BLOCKSIZE 512
 
788
   {
 
789
      struct user ua;
 
790
      uint64 old_ru_ioblock = proc_elem->ru_ioblock;
 
791
 
 
792
      /* need to do a table(2) call for each process to retrieve io usage data */   
 
793
      /* get user area stuff */
 
794
      if (table(TBL_UAREA, proc_elem->proc.pd_pid, (char *)&ua, 1, sizeof ua) == 1) {
 
795
         proc_elem->ru_ioblock = (uint64)(ua.u_ru.ru_inblock + ua.u_ru.ru_oublock);
 
796
         proc_elem->delta_chars = (proc_elem->ru_ioblock - old_ru_ioblock)* BLOCKSIZE;
 
797
      }
 
798
   }
 
799
#endif
 
800
 
 
801
 
 
802
   close(fd);
 
803
   DEXIT;
 
804
   return 0;
 
805
}
 
806
#endif
 
807
 
 
808
#endif /* (!COMPILE_DC) */