summary refs log tree commit diff
path: root/src/trap.c (follow)
Commit message (Collapse)AuthorAge
* [TRAP] Make sure evalskip is zero before running trapsHerbert Xu2014-10-02
| | | | | | | | | | | | | | | | | | | | | | | As it is if dotrap is called with evalskip set to a nonzero value, it'll try to execute any set traps. The result is that the first command in the first set trap will be executed while the rest of the trap will be silently ignored due to evalskip. This is highly counterintuitive, even though both bash and ksh exhibit a similar behaviour. This patch fixes it by skipping trap processing if evalskip is set on entry. It also adds a dotrap call to the top of evaltree to ensure that while continue; do continue; done has a chance of running traps. Finally the pendingsigs check is moved into dotrap for compactness. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
* [SIGNAL] Mark status as volatile in exitshellMaciej Żenczykowski2010-11-28
| | | | | | | | trap.c: In function 'exitshell': trap.c:354: warning: variable 'status' might be clobbered by 'longjmp' or 'vfork' Signed-off-by: Maciej Żenczykowski <zenczykowski@gmail.com> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
* [EVAL] Fixed trap/return regression due to SKIPEVAL removalHerbert Xu2010-11-28
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On Wed, Aug 11, 2010 at 08:06:16AM +0000, Guido Berhoerster wrote: > > with the latest git version of dash trap actions are not > evaluated in the context of a function. > > The following script demonstrates the bug: > ----8<---- > read_timeout () { > saved_traps="$(trap)" > trap 'printf "timed out\n"; eval "${saved_traps}"; return' TERM > ( sleep $1; kill -TERM $$ ) >/dev/null 2>&1 & > timer_pid=$! > read $2 > kill $timer_pid 2>/dev/null > } > > read_timeout 5 value > printf "read \"%s\"\n" "${value:=default}" > > ---->8---- > The return statement in the trap inside the read_timeout function > does not return from the function but rather exits the script. > > With dash 0.5.5.1 it works as expected. This bug was caused by the SKIPEVAL removal. When the SKIPEVAL hack was added to improve set -e support in traps, dotrap was changed to return whether set -e was detected. After the removal of SKIPEVAL, set -e is now handled through exraise. However, dotrap still returned a value which is now incorrectly used to trigger an exraise. This patch removes the vestigial link between dotrap and exraise. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
* [JOBS] Fix wait regression where it does not wait for all jobsHerbert Xu2010-05-27
| | | | | | | | | | | The sigsuspend patch broke wait by making it return after just one job has completed. This is because we rely on pendingsigs to signal work and never clear it until waitcmd finishes. This patch adds a separate gotsigchld for this purpose so we can clear it before we start waiting. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
* [EVAL] Force fork if any trap is set, not just on EXITJilles Tjoelker2010-05-27
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | In some cases the shell executes a subshell or an external command in the current process. This is not done if a trap on EXIT has been set, so that that trap can execute after the subshell or external command has finished. Extend that check to all traps. (A trap is "set" if a non-empty command string has been attached to it.) Improve encapsulation by exporting an accessor function for this and making the trap array static again. This is much like FreeBSD SVN r194127, enhanced to apply to subshells also (see FreeBSD SVN r194774). Example: dash -c '{ trap "echo moo" TERM; sleep 3; }& sleep 1; kill $!;wait' This should print "moo" after 3 seconds. Example: dash -c '{ trap "echo moo" TERM; (sleep 3) }& sleep 1; kill $!;wait' The same. Example: dash -c '{ trap "echo moo" TERM; sleep 3; :; }& sleep 1; kill $!;wait' This works correctly even without this patch. Signed-off-by: Jilles Tjoelker <jilles@stack.nl> Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
* [BUILTIN] Make trap signal name/number errors non-fatal.Herbert Xu2010-04-02
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | On Wed, Feb 24, 2010 at 10:23:34AM +0000, Peter Kjellerstedt wrote: > > there seems to be a problem with the trap implementation in dash > (tested with 0.5.4 and 0.5.5.1). If I specify a signal which is not > supported, the shell unconditionally aborts. E.g., I had expected > the following to print foo (like bash and zsh do): > > # dash -c 'trap "echo trap executed" UNKNOWNSIGNAL || echo "foo"' > trap: 1: UNKNOWNSIGNAL: bad trap > > This means I cannot write a construct like the following to take > advantage of the ERR signal which is present in some shells: > > trap "echo ERR trap executed" ERR 2>/dev/null || : > > I also checked the POSIX documentation, and quoting from > http://www.opengroup.org/onlinepubs/009695399/utilities/trap.html > (exit status): "For both interactive and non-interactive shells, > invalid signal names [XSI] [Option Start] or numbers [Option End] > shall not be considered a syntax error and do not cause the shell > to abort." This patch replaces sh_error with a outfmt + return 1 in trapcmd so that these errors are no longer fatal. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
* [EVAL] Pass EV_TESTED into evalcmdHerbert Xu2009-08-11
| | | | | | | | | | | | | | | | | | This patch fixes the case where the eval command is used with set -e and as part of a construct that should not cause the shell to abort, e.g., as part of the condition of an if statement. This is achieved by propagating the EV_TESTED flag into the evalstring function through evalcmd. As this alters the prototype of evalcmd it is now invoked explicitly by evalbltin. The built-in infrastructure has been changed to accomodate this special case. In order to ensure that the EXIT trap is properly executed this patch clears evalskip in exitshell. This wasn't needed before because of the broken way evalstring worked where it always clears evalskip when called by minusc. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
* [SIGNAL] Remove EXSIGHerbert Xu2009-02-22
| | | | | | Now that waitcmd no longer uses EXSIG we can remove it. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
* [JOBS] Fix dowait signal raceHerbert Xu2009-02-22
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This test program by Alexey Gladkov can cause dash to enter an infinite loop in waitcmd. #!/bin/dash trap "echo TRAP" USR1 stub() { echo ">>> STUB $1" >&2 sleep $1 echo "<<< STUB $1" >&2 kill -USR1 $$ } stub 3 & stub 2 & until { echo "###"; wait; } do echo "*** $?" done The problem is that if we get a signal after the wait3 system call has returned but before we get to INTON in dowait, then we can jump back up to the top and lose the exit status. So if we then wait for the job that has just exited, then it'll stay there forever. I made the original change that caused this bug to fix pretty much the same bug but in the opposite direction. That is, if we get a signal after we enter wait3 but before we hit the kernel then it too can cause the wait to go on forever (assuming the child doesn't exit). In fact this is pretty much exactly the scenario that you'll find in glibc's documentation on pause(). The solution is given there too, in the form of sigsuspend, which is the only way to do the check and wait atomically. So this patch fixes Alexey's race without reintroducing the old bug by converting the blocking wait3 to a sigsuspend. In order to do this we need to set a signal handler for SIGCHLD, so the code has been modified to always do that. Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
* [SHELL] Move flushall to the point just before _exitHerbert Xu2007-09-22
| | | | | | We need to flush at the very end in case we've generated any errors before that. The flushall call cannot perform a longjmp so it's safe there.
* [SHELL] Restore foreground process group on exitHerbert Xu2007-09-22
| | | | | | | | | | | | | | | | | On Thu, Jun 07, 2007 at 12:20:27PM +0200, Denis Vlasenko wrote: > > When I start dash under Midnight Commander and then type 'exit', dash > exits all right, but then MC is sent to background. It happens because > dash does not restore current process group on exit. > > Attached patch fixes this. It also fixes another bug: setjobctl(0) > must ignore tcsetpgrp errors, because there are cases when tty is > destroyed under dash. > > Patch is run-tested. I've fixed this slightly differently so that we don't need the xtcsetpgrp change.
* [EVAL] Make eval with empty arguments return 0 Herbert Xu2006-01-12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | On Tue, Jan 10, 2006 at 10:56:23AM +0000, Gerrit Pape wrote: > tags 347232 + patch > quit > > On Mon, Jan 09, 2006 at 04:29:19PM +0100, Marco Nenciarini wrote: > > The problem is here: > > > > # Set the kernel 2.6 option only for fresh install > > test -z "$(GetMenuOpt "kopt" "")" && kopt_2_6="root=$root_device_2_6 ro" > > > > # Extract options for specific kernels > > eval $(ExtractMenuOpts "\(kopt_[a-zA-Z0-9_]\+\)") > > > > If the first test fails and the eval argument is empty then dash > > terminate with exitcode 1. > > > This is a simple testcase: > > tm:~# bash -c "set -e ;/bin/false && : ; eval ''; echo 'END'"; echo $? > > END > > 0 > > tm:~# dash -c "set -e ;/bin/false && : ; eval ''; echo 'END'"; echo $? > > 1 > > > > if you insert any command with successfull exit status before the > > empty eval, all work ok: > > tm:~# bash -c "set -e ;/bin/false && : ; : ; eval ''; echo 'END'"; echo $? > > END > > 0 > > tm:~# dash -c "set -e ;/bin/false && : ; : ; eval ''; echo 'END'"; echo $? > > END > > 0 > > Yes, I can confirm this is a bug in dash. The standard says > > EXIT STATUS > > If there are no arguments, or only null arguments, eval shall > return a zero exit status; otherwise, it shall return the exit > status of the command defined by the string of concatenated > arguments separated by <space>s. > > Hi Herbert, please see http://bugs.debian.org/347232 Changed evalstring to return the exit status instead of evalskip. This allows us to return zero if the string is empty.
* Copyright/licence updates and remove all traces of sys/cdefs.hHerbert Xu2005-10-29
| | | | | | | | | | | This change updates the BSD licence to the three-clause version since NetBSD has already done so. This makes dash GPL-compatible. It also adds Christos Zoulas (NetBSD ash maintainer) to the COPYING file. I've added "copyright by Herbert Xu" to most files. Finally all CVS IDs and inclusion of sys/cdefs.h have been removed. The latter is needed for support of klibc.
* Added eflag fixes for trap and minusc.herbert2005-09-26
| | | | | | Let evaltree handle traps from cmdloop. Reset evalskip after minusc is executed. Stop executing traps once SKIPEVAL is seen.
* Renamed error to sh_error.herbert2005-09-26
|
* Only reread exitstatus on EXEXIT in exitshell.herbert2005-09-26
|
* Initial import.Herbert Xu2005-09-26