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>