From owner-svn-src-all@FreeBSD.ORG Mon Jan 16 11:07:46 2012 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id BDC76106564A; Mon, 16 Jan 2012 11:07:46 +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 A1C088FC1D; Mon, 16 Jan 2012 11:07:46 +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 q0GB7k4v031671; Mon, 16 Jan 2012 11:07:46 GMT (envelope-from dumbbell@svn.freebsd.org) Received: (from dumbbell@localhost) by svn.freebsd.org (8.14.4/8.14.4/Submit) id q0GB7kY3031665; Mon, 16 Jan 2012 11:07:46 GMT (envelope-from dumbbell@svn.freebsd.org) Message-Id: <201201161107.q0GB7kY3031665@svn.freebsd.org> From: Jean-Sebastien Pedron Date: Mon, 16 Jan 2012 11:07:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r230212 - in head: bin/sh tools/regression/bin/sh/builtins X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 16 Jan 2012 11:07:46 -0000 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