Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 16 Jan 2012 11:07:46 +0000 (UTC)
From:      Jean-Sebastien Pedron <dumbbell@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r230212 - in head: bin/sh tools/regression/bin/sh/builtins
Message-ID:  <201201161107.q0GB7kY3031665@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: dumbbell
Date: Mon Jan 16 11:07:46 2012
New Revision: 230212
URL: http://svn.freebsd.org/changeset/base/230212

Log:
  sh: Fix execution of multiple statements in a trap when evalskip is set
  
  Before this fix, only the first statement of the trap was executed if
  evalskip was set. This is for example the case when:
      o  "-e" is set for this shell
      o  a trap is set on EXIT
      o  a function returns 1 and causes the script to abort
  
  Reviewed by:	jilles
  MFC after:	2 weeks

Added:
  head/tools/regression/bin/sh/builtins/trap10.0   (contents, props changed)
  head/tools/regression/bin/sh/builtins/trap11.0   (contents, props changed)
Modified:
  head/bin/sh/eval.c
  head/bin/sh/eval.h
  head/bin/sh/trap.c

Modified: head/bin/sh/eval.c
==============================================================================
--- head/bin/sh/eval.c	Mon Jan 16 10:59:44 2012	(r230211)
+++ head/bin/sh/eval.c	Mon Jan 16 11:07:46 2012	(r230212)
@@ -75,7 +75,7 @@ __FBSDID("$FreeBSD$");
 
 
 int evalskip;			/* set if we are skipping commands */
-static int skipcount;		/* number of levels to skip */
+int skipcount;			/* number of levels to skip */
 MKINIT int loopnest;		/* current loop nesting level */
 int funcnest;			/* depth of function calls */
 static int builtin_flags;	/* evalcommand flags for builtins */

Modified: head/bin/sh/eval.h
==============================================================================
--- head/bin/sh/eval.h	Mon Jan 16 10:59:44 2012	(r230211)
+++ head/bin/sh/eval.h	Mon Jan 16 11:07:46 2012	(r230212)
@@ -60,6 +60,7 @@ void evalbackcmd(union node *, struct ba
 #define in_function()	funcnest
 extern int funcnest;
 extern int evalskip;
+extern int skipcount;
 
 /* reasons for skipping commands (see comment on breakcmd routine) */
 #define SKIPBREAK	1

Modified: head/bin/sh/trap.c
==============================================================================
--- head/bin/sh/trap.c	Mon Jan 16 10:59:44 2012	(r230211)
+++ head/bin/sh/trap.c	Mon Jan 16 11:07:46 2012	(r230212)
@@ -412,7 +412,7 @@ void
 dotrap(void)
 {
 	int i;
-	int savestatus;
+	int savestatus, prev_evalskip, prev_skipcount;
 
 	in_dotrap++;
 	for (;;) {
@@ -427,10 +427,36 @@ dotrap(void)
 					 */
 					if (i == SIGCHLD)
 						ignore_sigchld++;
+
+					/*
+					 * Backup current evalskip
+					 * state and reset it before
+					 * executing a trap, so that the
+					 * trap is not disturbed by an
+					 * ongoing break/continue/return
+					 * statement.
+					 */
+					prev_evalskip  = evalskip;
+					prev_skipcount = skipcount;
+					evalskip = 0;
+
 					last_trapsig = i;
 					savestatus = exitstatus;
 					evalstring(trap[i], 0);
 					exitstatus = savestatus;
+
+					/*
+					 * If such a command was not
+					 * already in progress, allow a
+					 * break/continue/return in the
+					 * trap action to have an effect
+					 * outside of it.
+					 */
+					if (prev_evalskip != 0) {
+						evalskip  = prev_evalskip;
+						skipcount = prev_skipcount;
+					}
+
 					if (i == SIGCHLD)
 						ignore_sigchld--;
 				}
@@ -501,6 +527,11 @@ exitshell_savedstatus(void)
 	}
 	handler = &loc1;
 	if ((p = trap[0]) != NULL && *p != '\0') {
+		/*
+		 * Reset evalskip, or the trap on EXIT could be
+		 * interrupted if the last command was a "return".
+		 */
+		evalskip = 0;
 		trap[0] = NULL;
 		evalstring(p, 0);
 	}

Added: head/tools/regression/bin/sh/builtins/trap10.0
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/bin/sh/builtins/trap10.0	Mon Jan 16 11:07:46 2012	(r230212)
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+# Check that the return statement will not break the EXIT trap, ie. all
+# trap commands are executed before the script exits.
+
+test "$(trap 'printf trap; echo ped' EXIT; f() { return; }; f)" = trapped || exit 1

Added: head/tools/regression/bin/sh/builtins/trap11.0
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ head/tools/regression/bin/sh/builtins/trap11.0	Mon Jan 16 11:07:46 2012	(r230212)
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+# Check that the return statement will not break the USR1 trap, ie. all
+# trap commands are executed before the script resumes.
+
+result=$(${SH} -c 'trap "printf trap; echo ped" USR1; f() { return $(kill -USR1 $$); }; f')
+test $? -eq 0 || exit 1
+test "$result" = trapped || exit 1



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