From owner-svn-src-stable-9@FreeBSD.ORG Mon Feb 6 13:29:51 2012 Return-Path: Delivered-To: svn-src-stable-9@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 7D0DE106566B; Mon, 6 Feb 2012 13:29:51 +0000 (UTC) (envelope-from dumbbell@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 69EF48FC17; Mon, 6 Feb 2012 13:29:51 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.4/8.14.4) with ESMTP id q16DTphZ037870; Mon, 6 Feb 2012 13:29:51 GMT (envelope-from dumbbell@svn.freebsd.org) Received: (from dumbbell@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q16DTp3v037863; Mon, 6 Feb 2012 13:29:51 GMT (envelope-from dumbbell@svn.freebsd.org) Message-Id: <201202061329.q16DTp3v037863@svn.freebsd.org> From: Jean-Sebastien Pedron Date: Mon, 6 Feb 2012 13:29:51 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-9@freebsd.org X-SVN-Group: stable-9 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r231085 - in stable/9: bin/sh tools/regression/bin/sh/builtins X-BeenThere: svn-src-stable-9@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for only the 9-stable src tree List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 Feb 2012 13:29:51 -0000 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