Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 23 Apr 2011 22:28:57 +0000 (UTC)
From:      Jilles Tjoelker <jilles@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r220978 - in head: bin/sh tools/regression/bin/sh/execution
Message-ID:  <201104232228.p3NMSvJb006127@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jilles
Date: Sat Apr 23 22:28:56 2011
New Revision: 220978
URL: http://svn.freebsd.org/changeset/base/220978

Log:
  sh: Allow EV_EXIT through function calls, make {...} <redir more consistent.
  
  If EV_EXIT causes an exit, use the exception mechanism to unwind
  redirections and local variables. This way, if the final command is a
  redirected command, an EXIT trap now executes without the redirections.
  
  Because of these changes, EV_EXIT can now be inherited by the body of a
  function, so do so. This means that a function no longer prevents a fork
  before an exec being skipped, such as in
    f() { head -1 /etc/passwd; }; echo $(f)
  
  Wrapping a single builtin in a function may still cause an otherwise
  unnecessary fork with command substitution, however.
  
  An exit command or -e failure still invokes the EXIT trap with the
  original redirections and local variables in place.
  
  Note: this depends on SHELLPROC being gone. A SHELLPROC depended on
  keeping the redirections and local variables and only cleaning up the
  state to restore them.

Added:
  head/tools/regression/bin/sh/execution/fork3.0   (contents, props changed)
  head/tools/regression/bin/sh/execution/redir6.0   (contents, props changed)
  head/tools/regression/bin/sh/execution/redir7.0   (contents, props changed)
Modified:
  head/bin/sh/error.h
  head/bin/sh/eval.c
  head/bin/sh/main.c

Modified: head/bin/sh/error.h
==============================================================================
--- head/bin/sh/error.h	Sat Apr 23 21:38:21 2011	(r220977)
+++ head/bin/sh/error.h	Sat Apr 23 22:28:56 2011	(r220978)
@@ -57,6 +57,7 @@ extern volatile sig_atomic_t exception;
 #define EXINT 0		/* SIGINT received */
 #define EXERROR 1	/* a generic error */
 #define EXEXEC 2	/* command execution failed */
+#define EXEXIT 3	/* call exitshell(exitstatus) */
 
 
 /*

Modified: head/bin/sh/eval.c
==============================================================================
--- head/bin/sh/eval.c	Sat Apr 23 21:38:21 2011	(r220977)
+++ head/bin/sh/eval.c	Sat Apr 23 22:28:56 2011	(r220978)
@@ -179,7 +179,7 @@ evalstring(char *s, int flags)
 	if (!any)
 		exitstatus = 0;
 	if (flags_exit)
-		exitshell(exitstatus);
+		exraise(EXEXIT);
 }
 
 
@@ -285,8 +285,10 @@ evaltree(union node *n, int flags)
 out:
 	if (pendingsigs)
 		dotrap();
-	if ((flags & EV_EXIT) || (eflag && exitstatus != 0 && do_etest))
+	if (eflag && exitstatus != 0 && do_etest)
 		exitshell(exitstatus);
+	if (flags & EV_EXIT)
+		exraise(EXEXIT);
 }
 
 
@@ -440,8 +442,8 @@ evalredir(union node *n, int flags)
 
 		handler = savehandler;
 		e = exception;
+		popredir();
 		if (e == EXERROR || e == EXEXEC) {
-			popredir();
 			if (in_redirect) {
 				exitstatus = 2;
 				return;
@@ -927,8 +929,7 @@ evalcommand(union node *cmd, int flags, 
 		if (setjmp(jmploc.loc)) {
 			freeparam(&shellparam);
 			shellparam = saveparam;
-			if (exception == EXERROR || exception == EXEXEC)
-				popredir();
+			popredir();
 			unreffunc(cmdentry.u.func);
 			poplocalvars();
 			localvars = savelocalvars;
@@ -943,10 +944,8 @@ evalcommand(union node *cmd, int flags, 
 		for (sp = varlist.list ; sp ; sp = sp->next)
 			mklocal(sp->text);
 		exitstatus = oexitstatus;
-		if (flags & EV_TESTED)
-			evaltree(getfuncnode(cmdentry.u.func), EV_TESTED);
-		else
-			evaltree(getfuncnode(cmdentry.u.func), 0);
+		evaltree(getfuncnode(cmdentry.u.func),
+		    flags & (EV_TESTED | EV_EXIT));
 		INTOFF;
 		unreffunc(cmdentry.u.func);
 		poplocalvars();
@@ -982,7 +981,10 @@ evalcommand(union node *cmd, int flags, 
 		savehandler = handler;
 		if (setjmp(jmploc.loc)) {
 			e = exception;
-			exitstatus = (e == EXINT)? SIGINT+128 : 2;
+			if (e == EXINT)
+				exitstatus = SIGINT+128;
+			else if (e != EXEXIT)
+				exitstatus = 2;
 			goto cmddone;
 		}
 		handler = &jmploc;
@@ -1018,8 +1020,7 @@ cmddone:
 			backcmd->nleft = memout.nextc - memout.buf;
 			memout.buf = NULL;
 		}
-		if (cmdentry.u.index != EXECCMD &&
-				(e == -1 || e == EXERROR || e == EXEXEC))
+		if (cmdentry.u.index != EXECCMD)
 			popredir();
 		if (e != -1) {
 			if ((e != EXERROR && e != EXEXEC)

Modified: head/bin/sh/main.c
==============================================================================
--- head/bin/sh/main.c	Sat Apr 23 21:38:21 2011	(r220977)
+++ head/bin/sh/main.c	Sat Apr 23 22:28:56 2011	(r220978)
@@ -111,7 +111,8 @@ main(int argc, char *argv[])
 			break;
 		}
 
-		if (state == 0 || iflag == 0 || ! rootshell)
+		if (state == 0 || iflag == 0 || ! rootshell ||
+		    exception == EXEXIT)
 			exitshell(exitstatus);
 		reset();
 		if (exception == EXINT)

Added: head/tools/regression/bin/sh/execution/fork3.0
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/bin/sh/execution/fork3.0	Sat Apr 23 22:28:56 2011	(r220978)
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+result=$(${SH} -c 'f() { ps -p $$ -o comm=; }; f')
+test "$result" = "ps"

Added: head/tools/regression/bin/sh/execution/redir6.0
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/bin/sh/execution/redir6.0	Sat Apr 23 22:28:56 2011	(r220978)
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+failures=0
+
+check() {
+	if [ "$2" != "$3" ]; then
+		echo "Failure at $1" >&2
+		failures=$((failures + 1))
+	fi
+}
+
+check $LINENO "$(trap "echo bye" EXIT; : >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; { :; } >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; (:) >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; (: >/dev/null))" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; : >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; { :; } >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; (:) >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; (: >/dev/null)')" bye
+
+exit $((failures > 0))

Added: head/tools/regression/bin/sh/execution/redir7.0
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/bin/sh/execution/redir7.0	Sat Apr 23 22:28:56 2011	(r220978)
@@ -0,0 +1,21 @@
+# $FreeBSD$
+
+failures=0
+
+check() {
+	if [ "$2" != "$3" ]; then
+		echo "Failure at $1" >&2
+		failures=$((failures + 1))
+	fi
+}
+
+check $LINENO "$(trap "echo bye" EXIT; f() { :; }; f >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; f() { :; }; { f; } >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; f() { :; }; (f) >/dev/null)" bye
+check $LINENO "$(trap "echo bye" EXIT; f() { :; }; (f >/dev/null))" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; f() { :; }; f >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; f() { :; }; { f; } >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; f() { :; }; (f) >/dev/null')" bye
+check $LINENO "$(${SH} -c 'trap "echo bye" EXIT; f() { :; }; (f >/dev/null)')" bye
+
+exit $((failures > 0))



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201104232228.p3NMSvJb006127>