svn commit: r231085 - in stable/9: bin/sh
tools/regression/bin/sh/builtins
Jean-Sebastien Pedron
dumbbell at FreeBSD.org
Mon Feb 6 13:29:51 UTC 2012
Author: dumbbell
Date: Mon Feb 6 13:29:50 2012
New Revision: 231085
URL: http://svn.freebsd.org/changeset/base/231085
Log:
MFC r230212:
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
Sponsored by: Yakaz (http://www.yakaz.com)
Added:
stable/9/tools/regression/bin/sh/builtins/trap10.0
- copied unchanged from r230212, head/tools/regression/bin/sh/builtins/trap10.0
stable/9/tools/regression/bin/sh/builtins/trap11.0
- copied unchanged from r230212, head/tools/regression/bin/sh/builtins/trap11.0
Modified:
stable/9/bin/sh/eval.c
stable/9/bin/sh/eval.h
stable/9/bin/sh/trap.c
Directory Properties:
stable/9/bin/sh/ (props changed)
stable/9/tools/ (props changed)
stable/9/tools/regression/bin/sh/ (props changed)
Modified: stable/9/bin/sh/eval.c
==============================================================================
--- stable/9/bin/sh/eval.c Mon Feb 6 13:26:12 2012 (r231084)
+++ stable/9/bin/sh/eval.c Mon Feb 6 13:29:50 2012 (r231085)
@@ -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: stable/9/bin/sh/eval.h
==============================================================================
--- stable/9/bin/sh/eval.h Mon Feb 6 13:26:12 2012 (r231084)
+++ stable/9/bin/sh/eval.h Mon Feb 6 13:29:50 2012 (r231085)
@@ -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: stable/9/bin/sh/trap.c
==============================================================================
--- stable/9/bin/sh/trap.c Mon Feb 6 13:26:12 2012 (r231084)
+++ stable/9/bin/sh/trap.c Mon Feb 6 13:29:50 2012 (r231085)
@@ -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);
}
Copied: stable/9/tools/regression/bin/sh/builtins/trap10.0 (from r230212, head/tools/regression/bin/sh/builtins/trap10.0)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ stable/9/tools/regression/bin/sh/builtins/trap10.0 Mon Feb 6 13:29:50 2012 (r231085, copy of r230212, head/tools/regression/bin/sh/builtins/trap10.0)
@@ -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
Copied: stable/9/tools/regression/bin/sh/builtins/trap11.0 (from r230212, head/tools/regression/bin/sh/builtins/trap11.0)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ stable/9/tools/regression/bin/sh/builtins/trap11.0 Mon Feb 6 13:29:50 2012 (r231085, copy of r230212, head/tools/regression/bin/sh/builtins/trap11.0)
@@ -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
More information about the svn-src-stable-9
mailing list