Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: bug with for and time



Peter Stephenson wrote:
> Still, both wait3() and the
> additional rusage elements came from BSD; maybe I can rely on either
> both or neither being available and skip the case where we can't tie
> usage to individual processes.

This is what I've done.  I'm not sure doing anything else is necessary
or sensible.  Enjoy.

I replaced the fork()s with zfork()s as threatened.  As far as I can
see, the only issue is error messages, and they're not very common
errors.  They should still print something sensible.

Index: configure.ac
===================================================================
RCS file: /cvsroot/zsh/zsh/configure.ac,v
retrieving revision 1.20
diff -u -r1.20 configure.ac
--- configure.ac	7 Oct 2004 09:45:43 -0000	1.20
+++ configure.ac	8 Oct 2004 14:13:15 -0000
@@ -1448,6 +1448,32 @@
 
 
 dnl --------------------------------------------
+dnl Check for members of struct rusage
+dnl --------------------------------------------
+if test $ac_cv_func_getrusage = yes; then
+  AC_CHECK_MEMBERS([struct rusage.ru_maxrss,
+		    struct rusage.ru_ixrss,
+		    struct rusage.ru_idrss,
+		    struct rusage.ru_isrss,
+		    struct rusage.ru_minflt,
+		    struct rusage.ru_majflt,
+		    struct rusage.ru_nswap,
+		    struct rusage.ru_inblock,
+		    struct rusage.ru_oublock,
+		    struct rusage.ru_msgsnd,
+		    struct rusage.ru_msgrcv,
+		    struct rusage.ru_nsignals,
+		    struct rusage.ru_nvcsw,
+		    struct rusage.ru_nivcsw],,,
+[#include <sys/types.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/resource.h>])
+fi
+
+
+dnl --------------------------------------------
 dnl CHECK FOR DEFAULT PATH (used for command -p)
 dnl --------------------------------------------
 AC_CACHE_VAL(zsh_cv_cs_path,
Index: Doc/Zsh/params.yo
===================================================================
RCS file: /cvsroot/zsh/zsh/Doc/Zsh/params.yo,v
retrieving revision 1.22
diff -u -r1.22 params.yo
--- Doc/Zsh/params.yo	22 Jun 2004 13:10:02 -0000	1.22
+++ Doc/Zsh/params.yo	8 Oct 2004 14:13:18 -0000
@@ -1047,7 +1047,9 @@
 item(tt(TIMEFMT))(
 The format of process time reports with the tt(time) keyword.
 The default is `tt(%E real  %U user  %S system  %P %J)'.
-Recognizes the following escape sequences:
+Recognizes the following escape sequences, although not all
+may be available on all systems, and some that are available
+may not be useful:
 
 startsitem()
 sitem(tt(%%))(A `tt(%)'.)
@@ -1055,6 +1057,23 @@
 sitem(tt(%S))(CPU seconds spent in kernel mode.)
 sitem(tt(%E))(Elapsed time in seconds.)
 sitem(tt(%P))(The CPU percentage, computed as (tt(%U)PLUS()tt(%S))/tt(%E).)
+sitem(tt(%W))(Number of times the process was swapped.)
+sitem(tt(%X))(The average amount in (shared) text space used in Kbytes.)
+sitem(tt(%D))(The average amount in (unshared) data/stack space used in
+Kbytes.)
+sitem(tt(%K))(The total space used (%X+%D) in Kbytes.)
+sitem(tt(%M))(The  maximum memory the process had in use at any time in
+Kbytes.)
+sitem(tt(%F))(The number of major page faults (page needed to be brought
+from disk).)
+sitem(tt(%R))(The number of minor page faults.)
+sitem(tt(%I))(The number of input operations.)
+sitem(tt(%O))(The number of output operations.)
+sitem(tt(%r))(The number of socket messages received.)
+sitem(tt(%s))(The number of socket messages sent.)
+sitem(tt(%k))(The number of signals received.)
+sitem(tt(%w))(Number of voluntary context switches (waits).)
+sitem(tt(%c))(Number of involuntary context switches.)
 sitem(tt(%J))(The name of this job.)
 endsitem()
 
Index: Src/exec.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/exec.c,v
retrieving revision 1.73
diff -u -r1.73 exec.c
--- Src/exec.c	7 Oct 2004 09:45:46 -0000	1.73
+++ Src/exec.c	8 Oct 2004 14:13:25 -0000
@@ -1162,18 +1162,14 @@
 		      (jobtab[list_pipe_job].stat & STAT_STOPPED)))) {
 		    pid_t pid;
 		    int synch[2];
-		    struct timezone dummy_tz;
 		    struct timeval bgtime;
 
 		    pipe(synch);
 
-		    gettimeofday(&bgtime, &dummy_tz);
-		    /* Any reason this isn't zfork? */
-		    if ((pid = fork()) == -1) {
+		    if ((pid = zfork(&bgtime)) == -1) {
 			trashzle();
 			close(synch[0]);
 			close(synch[1]);
-			putc('\n', stderr);
 			fprintf(stderr, "zsh: job can't be suspended\n");
 			fflush(stderr);
 			makerunning(jn);
@@ -1300,15 +1296,11 @@
 	if (wc_code(code) >= WC_CURSH && (how & Z_SYNC)) {
 	    int synch[2];
 	    struct timeval bgtime;
-	    struct timezone dummy_tz;
 
 	    pipe(synch);
-	    gettimeofday(&bgtime, &dummy_tz);
-	    /* any reason this isn't zfork? */
-	    if ((pid = fork()) == -1) {
+	    if ((pid = zfork(&bgtime)) == -1) {
 		close(synch[0]);
 		close(synch[1]);
-		zerr("fork failed: %e", NULL, errno);
 	    } else if (pid) {
 		char dummy, *text;
 
Index: Src/jobs.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/jobs.c,v
retrieving revision 1.32
diff -u -r1.32 jobs.c
--- Src/jobs.c	7 Oct 2004 09:45:46 -0000	1.32
+++ Src/jobs.c	8 Oct 2004 14:13:28 -0000
@@ -271,6 +271,7 @@
 }
 
 
+#ifndef HAVE_GETRUSAGE
 /* Update status of process that we have just WAIT'ed for */
 
 /**/
@@ -278,32 +279,19 @@
 update_process(Process pn, int status)
 {
     struct timezone dummy_tz;
-#ifdef HAVE_GETRUSAGE
-    struct timeval childs, childu;
-#else
     long childs, childu;
-#endif
 
-#ifdef HAVE_GETRUSAGE
-    childs = child_usage.ru_stime;
-    childu = child_usage.ru_utime;
-#else
     childs = shtms.tms_cstime;
     childu = shtms.tms_cutime;
-#endif
     /* get time-accounting info          */
     get_usage();
     gettimeofday(&pn->endtime, &dummy_tz);  /* record time process exited        */
 
     pn->status = status;                    /* save the status returned by WAIT  */
-#ifdef HAVE_GETRUSAGE
-    dtime(&pn->ti.sys, &childs, &child_usage.ru_stime);
-    dtime(&pn->ti.usr, &childu, &child_usage.ru_utime);
-#else
     pn->ti.st  = shtms.tms_cstime - childs; /* compute process system space time */
     pn->ti.ut  = shtms.tms_cutime - childu; /* compute process user space time   */
-#endif
 }
+#endif
 
 /* Update status of job, possibly printing it */
 
@@ -563,6 +551,9 @@
 {
     char *s;
     double elapsed_time, user_time, system_time;
+#ifdef HAVE_GETRUSAGE
+    double total_time;
+#endif
     int percent;
 
     if (!desc)
@@ -572,10 +563,11 @@
     elapsed_time = real->tv_sec + real->tv_usec / 1000000.0;
 
 #ifdef HAVE_GETRUSAGE
-    user_time = ti->usr.tv_sec + ti->usr.tv_usec / 1000000.0;
-    system_time = ti->sys.tv_sec + ti->sys.tv_usec / 1000000.0;
+    user_time = ti->ru_utime.tv_sec + ti->ru_utime.tv_usec / 1000000.0;
+    system_time = ti->ru_stime.tv_sec + ti->ru_stime.tv_usec / 1000000.0;
     percent = 100.0 * (user_time + system_time)
 	/ (real->tv_sec + real->tv_usec / 1000000.0);
+    total_time = user_time + system_time;
 #else
     set_clktck();
     user_time    = ti->ut / (double) clktck;
@@ -620,6 +612,97 @@
 	    case 'P':
 		fprintf(stderr, "%d%%", percent);
 		break;
+#ifdef HAVE_STRUCT_RUSAGE_RU_NSWAP
+	    case 'W':
+		fprintf(stderr, "%ld", ti->ru_nswap);
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_IXRSS
+	    case 'X':
+		fprintf(stderr, "%ld", (long)(ti->ru_ixrss / total_time));
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_IDRSS
+	    case 'D':
+		fprintf(stderr, "%ld",
+			(long) ((ti->ru_idrss
+#ifdef HAVE_STRUCT_RUSAGE_RU_ISRSS
+				 + ti->ru_isrss
+#endif
+				    ) / total_time));
+		break;
+#endif
+#if defined(HAVE_STRUCT_RUSAGE_RU_IDRSS) || \
+    defined(HAVE_STRUCT_RUSAGE_RU_ISRSS) || \
+    defined(HAVE_STRUCT_RUSAGE_RU_IXRSS)
+	    case 'K':
+		/* treat as D if X not available */
+		fprintf(stderr, "%ld",
+			(long) ((
+#ifdef HAVE_STRUCT_RUSAGE_RU_IXRSS
+				    ti->ru_ixrss
+#else
+				    0
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_IDRSS
+				    + ti->ru_idrss
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_ISRSS
+				    + ti->ru_isrss
+#endif
+				    ) / total_time));
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_MAXRSS
+	    case 'M':
+		fprintf(stderr, "%ld", ti->ru_maxrss / 1024);
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_MAJFLT
+	    case 'F':
+		fprintf(stderr, "%ld", ti->ru_majflt);
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_MINFLT
+	    case 'R':
+		fprintf(stderr, "%ld", ti->ru_minflt);
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_INBLOCK
+	    case 'I':
+		fprintf(stderr, "%ld", ti->ru_inblock);
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_OUBLOCK
+	    case 'O':
+		fprintf(stderr, "%ld", ti->ru_oublock);
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_MSGRCV
+	    case 'r':
+		fprintf(stderr, "%ld", ti->ru_msgrcv);
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_MSGSND
+	    case 's':
+		fprintf(stderr, "%ld", ti->ru_msgsnd);
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_NSIGNALS
+	    case 'k':
+		fprintf(stderr, "%ld", ti->ru_nsignals);
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_NVCSW
+	    case 'w':
+		fprintf(stderr, "%ld", ti->ru_nvcsw);
+		break;
+#endif
+#ifdef HAVE_STRUCT_RUSAGE_RU_NIVCSW
+	    case 'c':
+		fprintf(stderr, "%ld", ti->ru_nivcsw);
+		break;
+#endif
 	    case 'J':
 		fprintf(stderr, "%s", desc);
 		break;
@@ -683,8 +766,9 @@
 	return 0;
 
 #ifdef HAVE_GETRUSAGE
-    reporttime -= j->procs->ti.usr.tv_sec + j->procs->ti.sys.tv_sec;
-    if (j->procs->ti.usr.tv_usec + j->procs->ti.sys.tv_usec >= 1000000)
+    reporttime -= j->procs->ti.ru_utime.tv_sec + j->procs->ti.ru_stime.tv_sec;
+    if (j->procs->ti.ru_utime.tv_usec +
+	j->procs->ti.ru_stime.tv_usec >= 1000000)
 	reporttime--;
     return reporttime <= 0;
 #else
@@ -1214,20 +1298,15 @@
 {
     struct timezone dummy_tz;
     struct timeval dtimeval, now;
-#ifdef HAVE_GETRUSAGE
-    struct rusage ru;
     child_times_t ti;
-#else
-    struct timeinfo ti;
+#ifndef HAVE_GETRUSAGE
     struct tms buf;
 #endif
 
     gettimeofday(&now, &dummy_tz);
 
 #ifdef HAVE_GETRUSAGE
-    getrusage(RUSAGE_SELF, &ru);
-    ti.sys = ru.ru_stime;
-    ti.usr = ru.ru_utime;
+    getrusage(RUSAGE_SELF, &ti);
 #else
     times(&buf);
 
@@ -1237,9 +1316,7 @@
     printtime(dtime(&dtimeval, &shtimer, &now), &ti, "shell");
 
 #ifdef HAVE_GETRUSAGE
-    getrusage(RUSAGE_CHILDREN, &ru);
-    ti.sys = ru.ru_stime;
-    ti.usr = ru.ru_utime;
+    getrusage(RUSAGE_CHILDREN, &ti);
 #else
     ti.ut = buf.tms_cutime;
     ti.st = buf.tms_cstime;
Index: Src/signals.c
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/signals.c,v
retrieving revision 1.31
diff -u -r1.31 signals.c
--- Src/signals.c	7 Oct 2004 09:45:46 -0000	1.31
+++ Src/signals.c	8 Oct 2004 14:13:31 -0000
@@ -400,18 +400,6 @@
     return ret;
 }
 
-/* What flavor of waitpid/wait3/wait shall we use? */
- 
-#ifdef HAVE_WAITPID
-# define  WAIT(pid, statusp, options) waitpid(pid, statusp, options)
-#else
-# ifdef HAVE_WAIT3
-#  define WAIT(pid, statusp, options) wait3((void *) statusp, options, NULL)
-# else
-#  define WAIT(pid, statusp, options) wait(statusp)
-# endif
-#endif
-
 /* the signal handler */
  
 /**/
@@ -471,7 +459,25 @@
 	    int *procsubval = &cmdoutval;
 	    struct execstack *es = exstack;
 
-            pid = WAIT(-1, &status, WNOHANG|WUNTRACED);  /* reap the child process */
+	    /*
+	     * Reap the child process.
+	     * If we want usage information, we need to use wait3.
+	     */
+#ifdef HAVE_WAIT3
+# ifdef HAVE_GETRUSAGE
+	    struct rusage ru;
+
+	    pid = wait3((void *)&status, WNOHANG|WUNTRACED, &ru);
+# else
+	    pid = wait3((void *)&status, WNOHANG|WUNTRACED, NULL);
+# endif
+#else
+# ifdef HAVE_WAITPID
+	    pid = waitpid(-1, &status, WNOHANG|WUNTRACED);
+# else
+	    pid = wait(&status);
+# endif
+#endif
 
             if (!pid)  /* no more children to reap */
                 break;
@@ -504,7 +510,14 @@
 
 	    /* Find the process and job containing this pid and update it. */
 	    if (findproc(pid, &jn, &pn, 0)) {
+#if defined(HAVE_WAIT3) && defined(HAVE_GETRUSAGE)
+		struct timezone dummy_tz;
+		gettimeofday(&pn->endtime, &dummy_tz);
+		pn->status = status;
+		pn->ti = ru;
+#else
 		update_process(pn, status);
+#endif
 		update_job(jn);
 	    } else if (findproc(pid, &jn, &pn, 1)) {
 		pn->status = status;
Index: Src/zsh.h
===================================================================
RCS file: /cvsroot/zsh/zsh/Src/zsh.h,v
retrieving revision 1.63
diff -u -r1.63 zsh.h
--- Src/zsh.h	7 Oct 2004 09:45:46 -0000	1.63
+++ Src/zsh.h	8 Oct 2004 14:13:35 -0000
@@ -740,10 +740,7 @@
 /* node in job process lists */
 
 #ifdef HAVE_GETRUSAGE
-typedef struct {
-    struct timeval sys;
-    struct timeval usr;
-} child_times_t;
+typedef struct rusage child_times_t;
 #else
 typedef struct timeinfo child_times_t;
 #endif

-- 
Peter Stephenson <pws@xxxxxxx>                  Software Engineer
CSR Ltd., Science Park, Milton Road,
Cambridge, CB4 0WH, UK                          Tel: +44 (0)1223 692070


**********************************************************************
This email and any files transmitted with it are confidential and
intended solely for the use of the individual or entity to whom they
are addressed. If you have received this email in error please notify
the system manager.

This footnote also confirms that this email message has been swept by
MIMEsweeper for the presence of computer viruses.

www.mimesweeper.com
**********************************************************************



Messages sorted by: Reverse Date, Date, Thread, Author