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

Re: Zsh 2.6-beta10 problem: builtin time/other builtin



jepler@xxxxxxxxxxxxxx wrote:
> 1.  Time of builtins -- All zsh 2.6 versions and platforms I have tested
> % which time echo
> time: shell reserved word
> echo: shell built-in command
> % time echo foo
> foo
> 
>     The alert eye will notice that there is no output of 'time' for that
> command.

This is a long-standing gripe which we really must fix sometime.


> 2.  Time in subshells -- Only linux 1.2.9, but with betas 8 and 10, the
> only versions I have tested
> % which time
> time: shell reserved word
> % ( time /bin/echo foo )
> foo
> 0.139s real  -11786.160s user  -1171.120s system  -9329435%
> 
>     The alert eye will notice that the user and system time taken by this
> 'echo' are less than trustworthy.  The 'real' time seems to be accurate,
> however.

There are actually two problems, both of which are fixed by the patch
(to 2.6-beta11-test4):

1) The obvious one.  This was very easy to fix:  the extra line in
entersubsh() resetting the totals for the time spent in the shell and
its children does this.  (Before, zsh was subtracting the total time
spent in children of the parent shell from the total time spent in
children of the subshell.)

2) I don't know if you'd noticed, but there's no text either (it
should say "/bin/echo foo" on the report line).  This is also a
problem when the MONITOR option is unset, in which case you never get
the name of the command being timed.  To fix this I restructured the
status flags that get passed around between execpline and execcmd so
that the latter now knows if the pipeline is being timed.  The easiest
way to allow this was to turn the Z_* flags determining the type of
pipeline into an or-able set in zsh.h.  Now execcmd() and entersubsh()
get the full pipeline type passed, not just the flag saying whether
they are in the background.  This makes the code a bit clearer and
more consistent, but does require more tests of the form 'how &
Z_ASYNC' instead of simply 'bkg': that's why the patch is so long.

*** Src/exec.c.job	Fri Sep 15 04:22:38 1995
--- Src/exec.c	Mon Sep 18 15:37:49 1995
***************
*** 588,597 ****
      initjob();
      jobtab[newjob].filelist = last_file_list;
      last_file_list = NULL;
!     if (how == Z_TIMED) {
  	jobtab[thisjob].stat |= STAT_TIMED;
- 	how = Z_SYNC;
-     }
      if (l->flags & PFLAG_COPROC) {
  	how = Z_ASYNC;
  	if (coprocin >= 0) {
--- 588,595 ----
      initjob();
      jobtab[newjob].filelist = last_file_list;
      last_file_list = NULL;
!     if (how & Z_TIMED)
  	jobtab[thisjob].stat |= STAT_TIMED;
      if (l->flags & PFLAG_COPROC) {
  	how = Z_ASYNC;
  	if (coprocin >= 0) {
***************
*** 612,618 ****
  	simple_pline = (l->left->type == END);
      execpline2(l->left, how, opipe[0], ipipe[1], last1);
      pline_level--;
!     if (how == Z_ASYNC) {
  	lastwj = newjob;
  	if (l->flags & PFLAG_COPROC)
  	    close(ipipe[1]);
--- 610,616 ----
  	simple_pline = (l->left->type == END);
      execpline2(l->left, how, opipe[0], ipipe[1], last1);
      pline_level--;
!     if (how & Z_ASYNC) {
  	lastwj = newjob;
  	if (l->flags & PFLAG_COPROC)
  	    close(ipipe[1]);
***************
*** 703,709 ****
  		    }
  		    else {
  			close(synch[0]);
! 			entersubsh(1, 0);
  			setpgrp(0L, mypgrp = jobtab[list_pipe_job].gleader);
  			close(synch[1]);
  			kill(getpid(), SIGSTOP);
--- 701,707 ----
  		    }
  		    else {
  			close(synch[0]);
! 			entersubsh(Z_ASYNC, 0);
  			setpgrp(0L, mypgrp = jobtab[list_pipe_job].gleader);
  			close(synch[1]);
  			kill(getpid(), SIGSTOP);
***************
*** 756,768 ****
      if (pline_level == 1)
  	strcpy(list_pipe_text, getjobtext((void *) pline->left));
      if (pline->type == END) {
! 	execcmd(pline->left, input, output, how == Z_ASYNC, last1);
  	pline->left = NULL;
      } else {
  	int old_list_pipe = list_pipe;
  
  	mpipe(pipes);
! 	if (pline->left->type >= CURSH && how == Z_SYNC) {
  	    int synch[2];
  
  	/* if we are doing "foo | bar" where foo is a current *
--- 754,766 ----
      if (pline_level == 1)
  	strcpy(list_pipe_text, getjobtext((void *) pline->left));
      if (pline->type == END) {
! 	execcmd(pline->left, input, output, how, last1);
  	pline->left = NULL;
      } else {
  	int old_list_pipe = list_pipe;
  
  	mpipe(pipes);
! 	if (pline->left->type >= CURSH && (how & Z_SYNC)) {
  	    int synch[2];
  
  	/* if we are doing "foo | bar" where foo is a current *
***************
*** 773,781 ****
  	    if (!(pid = fork())) {
  		close(pipes[0]);
  		close(synch[0]);
! 		entersubsh(how == Z_ASYNC, 1);
  		close(synch[1]);
! 		execcmd(pline->left, input, pipes[1], how == Z_ASYNC, 0);
  		_exit(lastval);
  	    } else if (pid == -1) {
  		close(synch[0]);
--- 771,779 ----
  	    if (!(pid = fork())) {
  		close(pipes[0]);
  		close(synch[0]);
! 		entersubsh(how, 1);
  		close(synch[1]);
! 		execcmd(pline->left, input, pipes[1], how, 0);
  		_exit(lastval);
  	    } else if (pid == -1) {
  		close(synch[0]);
***************
*** 792,798 ****
  	} else {
  	/* otherwise just do the pipeline normally. */
  	    subsh_close = pipes[0];
! 	    execcmd(pline->left, input, pipes[1], how == Z_ASYNC, 0);
  	}
  	pline->left = NULL;
  	close(pipes[1]);
--- 790,796 ----
  	} else {
  	/* otherwise just do the pipeline normally. */
  	    subsh_close = pipes[0];
! 	    execcmd(pline->left, input, pipes[1], how, 0);
  	}
  	pline->left = NULL;
  	close(pipes[1]);
***************
*** 1048,1054 ****
  
  /**/
  void
! execcmd(Cmd cmd, int input, int output, int bkg, int last1)
  {
      HashNode hn = NULL;
      Redir fn;
--- 1046,1052 ----
  
  /**/
  void
! execcmd(Cmd cmd, int input, int output, int how, int last1)
  {
      HashNode hn = NULL;
      Redir fn;
***************
*** 1100,1114 ****
      /* If the command begins with `%', then assume it is a *
       * reference to a job in the job table.                */
      if (nonempty(args) && *(char *)peekfirst(args) == '%') {
! 	pushnode(args, dupstring((bkg) ? "bg" : "fg"));
! 	bkg = 0;
      }
  
      /* If AUTORESUME is set, the command is SIMPLE, and doesn't have *
       * any redirections, then check if it matches as a prefix of a   *
       * job currently in the job table.  If it does, then we treat it *
       * as a command to resume this job.                              */
!     if (isset(AUTORESUME) && !bkg && empty(cmd->redir) && nonempty(args) &&
  	!input && type == SIMPLE && !nextnode(firstnode(args))) {
  	if (unset(NOTIFY))
  	    scanjobs();
--- 1098,1113 ----
      /* If the command begins with `%', then assume it is a *
       * reference to a job in the job table.                */
      if (nonempty(args) && *(char *)peekfirst(args) == '%') {
! 	pushnode(args, dupstring((how & Z_ASYNC) ? "bg" : "fg"));
! 	how = Z_SYNC;
      }
  
      /* If AUTORESUME is set, the command is SIMPLE, and doesn't have *
       * any redirections, then check if it matches as a prefix of a   *
       * job currently in the job table.  If it does, then we treat it *
       * as a command to resume this job.                              */
!     if (isset(AUTORESUME) && (how & Z_SYNC) &&
! 	empty(cmd->redir) && nonempty(args) &&
  	!input && type == SIMPLE && !nextnode(firstnode(args))) {
  	if (unset(NOTIFY))
  	    scanjobs();
***************
*** 1117,1123 ****
      }
  
      /* Get the text associated with this command. */
!     if (jobbing)
  	text = getjobtext((void *) cmd);
      else
  	text = NULL;
--- 1116,1122 ----
      }
  
      /* Get the text associated with this command. */
!     if (jobbing || (how & Z_TIMED))
  	text = getjobtext((void *) cmd);
      else
  	text = NULL;
***************
*** 1234,1246 ****
       * going into the background, or if we need to trap EXIT or    *
       * ZERR, fork.                                                 */
  
!     if (bkg || !(is_cursh || (cmd->flags & CFLAG_EXEC)) ||
  	((is_builtin | is_shfunc) && output)) {
  	int synch[2];
  
  	child_block();
  	pipe(synch);
! 	pid = (last1 && !bkg && !sigtrapped[SIGZERR]
  	       && !sigtrapped[SIGEXIT] && execok()) ? 0 : phork();
  	if (pid == -1) {
  	    close(synch[0]);
--- 1233,1245 ----
       * going into the background, or if we need to trap EXIT or    *
       * ZERR, fork.                                                 */
  
!     if ((how & Z_ASYNC) || !(is_cursh || (cmd->flags & CFLAG_EXEC)) ||
  	((is_builtin | is_shfunc) && output)) {
  	int synch[2];
  
  	child_block();
  	pipe(synch);
! 	pid = (last1 && (how & Z_SYNC) && !sigtrapped[SIGZERR]
  	       && !sigtrapped[SIGEXIT] && execok()) ? 0 : phork();
  	if (pid == -1) {
  	    close(synch[0]);
***************
*** 1254,1260 ****
  	    if (pid == -1)
  		zerr("%e", NULL, errno);
  	    else {
! 		if (bkg)
  		    lastpid = pid;
  		else if (!jobtab[thisjob].stty_in_env && nonempty(cmd->vars))
  		    while (nonempty(cmd->vars))	/* search for STTY=... */
--- 1253,1259 ----
  	    if (pid == -1)
  		zerr("%e", NULL, errno);
  	    else {
! 		if (how & Z_ASYNC)
  		    lastpid = pid;
  		else if (!jobtab[thisjob].stty_in_env && nonempty(cmd->vars))
  		    while (nonempty(cmd->vars))	/* search for STTY=... */
***************
*** 1267,1287 ****
  	    return;
  	}
  	close(synch[0]);
! 	entersubsh(bkg, 1);
  	close(synch[1]);
  	forked = 1;
  
  	if (sigtrapped[SIGINT] == 2)
  	    holdintr();
      } else if ((cmd->flags & CFLAG_EXEC) && !nullexec) {
! 	entersubsh(bkg, 1);
      } else {
      /* Job is running in current shell. */
  	jobtab[thisjob].stat |= STAT_CURSH;
      }
  
      /* background jobs run at lower priority if BGNICE is set */
!     if (bkg && isset(BGNICE))
  	nice(5);
  
      /* Perform postfork substitutions */
--- 1266,1286 ----
  	    return;
  	}
  	close(synch[0]);
! 	entersubsh(how, 1);
  	close(synch[1]);
  	forked = 1;
  
  	if (sigtrapped[SIGINT] == 2)
  	    holdintr();
      } else if ((cmd->flags & CFLAG_EXEC) && !nullexec) {
! 	entersubsh(how, 1);
      } else {
      /* Job is running in current shell. */
  	jobtab[thisjob].stat |= STAT_CURSH;
      }
  
      /* background jobs run at lower priority if BGNICE is set */
!     if ((how & Z_ASYNC) && isset(BGNICE))
  	nice(5);
  
      /* Perform postfork substitutions */
***************
*** 1586,1597 ****
  
  /**/
  void
! entersubsh(int bkg, int cl)
  {
      if (sigtrapped[SIGEXIT])
  	unsettrap(SIGEXIT);
      if (!jobbing) {
! 	if (bkg) {
  	    sigtrapped[SIGINT] = 2;
  	    signal_ignore(SIGINT);
  	    sigtrapped[SIGQUIT] = 2;
--- 1585,1596 ----
  
  /**/
  void
! entersubsh(int how, int cl)
  {
      if (sigtrapped[SIGEXIT])
  	unsettrap(SIGEXIT);
      if (!jobbing) {
! 	if (how & Z_ASYNC) {
  	    sigtrapped[SIGINT] = 2;
  	    signal_ignore(SIGINT);
  	    sigtrapped[SIGQUIT] = 2;
***************
*** 1612,1618 ****
  		    jobtab[thisjob].gleader = mypgrp;
  		setpgrp(0L, mypgrp);
  
! 		if (!bkg)
  		    attachtty(jobtab[thisjob].gleader);
  	    }
  	}
--- 1611,1617 ----
  		    jobtab[thisjob].gleader = mypgrp;
  		setpgrp(0L, mypgrp);
  
! 		if (how & Z_SYNC)
  		    attachtty(jobtab[thisjob].gleader);
  	    }
  	}
***************
*** 1622,1628 ****
  		!jobtab[list_pipe_job].gleader)
  		jobtab[list_pipe_job].gleader = jobtab[thisjob].gleader;
  	    setpgrp(0L, jobtab[thisjob].gleader);
! 	    if (!bkg)
  		attachtty(jobtab[thisjob].gleader);
  	} else
  	    setpgrp(0L, jobtab[thisjob].gleader);
--- 1621,1627 ----
  		!jobtab[list_pipe_job].gleader)
  		jobtab[list_pipe_job].gleader = jobtab[thisjob].gleader;
  	    setpgrp(0L, jobtab[thisjob].gleader);
! 	    if (how & Z_SYNC)
  		attachtty(jobtab[thisjob].gleader);
  	} else
  	    setpgrp(0L, jobtab[thisjob].gleader);
***************
*** 1649,1654 ****
--- 1648,1654 ----
      opts[USEZLE] = OPT_UNSET;
      if (cl)
  	clearjobtab();
+     times(&shtms);
  }
  
  /* close all internal shell fds */
***************
*** 1883,1889 ****
      subsh = 1;
      close(pipes[0]);
      redup(pipes[1], 1);
!     entersubsh(0, 1);
      signal_ignore(SIGTSTP);
      execlist(list, 1);
      close(1);
--- 1883,1889 ----
      subsh = 1;
      close(pipes[0]);
      redup(pipes[1], 1);
!     entersubsh(Z_SYNC, 1);
      signal_ignore(SIGTSTP);
      execlist(list, 1);
      close(1);
***************
*** 1981,1987 ****
      }
      subsh = 1;
      close(1);
!     entersubsh(0, 1);
      signal_ignore(SIGTSTP);
      (void)creat(nam, 0600);
      execlist(list, 1);
--- 1981,1987 ----
      }
      subsh = 1;
      close(1);
!     entersubsh(Z_SYNC, 1);
      signal_ignore(SIGTSTP);
      (void)creat(nam, 0600);
      execlist(list, 1);
***************
*** 2047,2053 ****
  	popheap();
  	return pnam;
      }
!     entersubsh(1, 1);
      closem();
      fd = open(pnam, O_WRONLY);
      if (fd == -1) {
--- 2047,2053 ----
  	popheap();
  	return pnam;
      }
!     entersubsh(Z_ASYNC, 1);
      closem();
      fd = open(pnam, O_WRONLY);
      if (fd == -1) {
***************
*** 2099,2105 ****
  	popheap();
  	return pnam;
      }
!     entersubsh(1, 1);
      closem();
      fd = open(pnam, O_RDONLY);
      redup(fd, 0);
--- 2099,2105 ----
  	popheap();
  	return pnam;
      }
!     entersubsh(Z_ASYNC, 1);
      closem();
      fd = open(pnam, O_RDONLY);
      redup(fd, 0);
***************
*** 2133,2139 ****
      }
      close(pipes[0]);
      closem();
!     entersubsh(1, 1);
      redup(pipes[1], 1);
      execlist(list, 1);
      _exit(lastval);
--- 2133,2139 ----
      }
      close(pipes[0]);
      closem();
!     entersubsh(Z_ASYNC, 1);
      redup(pipes[1], 1);
      execlist(list, 1);
      _exit(lastval);
***************
*** 2164,2170 ****
  	return pipes[1];
      }
      close(pipes[1]);
!     entersubsh(1, 1);
      redup(pipes[0], 0);
      closem();
      execlist(list, 1);
--- 2164,2170 ----
  	return pipes[1];
      }
      close(pipes[1]);
!     entersubsh(Z_ASYNC, 1);
      redup(pipes[0], 0);
      closem();
      execlist(list, 1);
***************
*** 2240,2246 ****
  	shelltime();
  	return 0;
      }
!     execpline(cmd->u.pline, Z_TIMED, 0);
      thisjob = jb;
      return lastval;
  }
--- 2240,2246 ----
  	shelltime();
  	return 0;
      }
!     execpline(cmd->u.pline, Z_TIMED|Z_SYNC, 0);
      thisjob = jb;
      return lastval;
  }
*** Src/text.c.job	Fri Sep 15 04:23:07 1995
--- Src/text.c	Mon Sep 18 14:21:05 1995
***************
*** 164,177 ****
      switch (NT_TYPE(n->ntype)) {
      case N_LIST:
  	gt2(_List(n)->left);
! 	if (_List(n)->type == Z_ASYNC)
  	    taddstr(" &");
  	simplifyright(_List(n));
  	if (_List(n)->right) {
  	    if (tnewlins)
  		taddnl();
  	    else
! 		taddstr((_List(n)->type == Z_ASYNC) ? " " : "; ");
  	    gt2(_List(n)->right);
  	}
  	break;
--- 164,177 ----
      switch (NT_TYPE(n->ntype)) {
      case N_LIST:
  	gt2(_List(n)->left);
! 	if (_List(n)->type & Z_ASYNC)
  	    taddstr(" &");
  	simplifyright(_List(n));
  	if (_List(n)->right) {
  	    if (tnewlins)
  		taddnl();
  	    else
! 		taddstr((_List(n)->type & Z_ASYNC) ? " " : "; ");
  	    gt2(_List(n)->right);
  	}
  	break;
*** Src/utils.c.job	Fri Sep 15 04:23:08 1995
--- Src/utils.c	Mon Sep 18 14:20:41 1995
***************
*** 1631,1637 ****
  	    List l = (List) n;
  
  	    l->left = (Sublist) simplifystruct((struct node *)l->left);
! 	    if (l->type == Z_SYNC && !l->right)
  		return (struct node *)l->left;
  	}
  	break;
--- 1631,1637 ----
  	    List l = (List) n;
  
  	    l->left = (Sublist) simplifystruct((struct node *)l->left);
! 	    if ((l->type & Z_SYNC) && !l->right)
  		return (struct node *)l->left;
  	}
  	break;
*** Src/zsh.h.job	Mon Sep 18 14:17:52 1995
--- Src/zsh.h	Mon Sep 18 14:17:32 1995
***************
*** 326,334 ****
      List right;
  };
  
! #define Z_SYNC  0		/* ; */
! #define Z_ASYNC 1		/* & */
! #define Z_TIMED 2
  
  /* tree element for sublists */
  
--- 326,334 ----
      List right;
  };
  
! #define Z_SYNC  1		/* ; */
! #define Z_ASYNC 2		/* & */
! #define Z_TIMED 4
  
  /* tree element for sublists */
  

-- 
Peter Stephenson <P.Stephenson@xxxxxxxxxxxxx>  Tel: +44 1792 205678 extn. 4461
WWW:  http://python.swan.ac.uk/~pypeters/      Fax: +44 1792 295324
Department of Physics, University of Wales, Swansea,
Singleton Park, Swansea, SA2 8PP, U.K.



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