Re: trap bug in recent versions of dash

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



* Jilles Tjoelker <jilles@xxxxxxxx> [2010-08-15 22:05]:
> On Wed, Aug 11, 2010 at 10:06:16AM +0200, Guido Berhoerster wrote:
> > with the latest git version of dash trap actions are not
> > evaluated in the context of a function.
> 
> I think dotrap()'s return value should be removed or at least ignored.
> An "evalskip" (break/continue/return-function/return-file) should never
> lead to an immediate exit. I'm not supplying a patch because I am not
> entirely sure about the side effects this could have.

OK, I'm not familiar with the source but it'd be nice to have it
fixed before the next release since it is a regression breaking
scripts.

> > The following script demonstrates the bug:
> > ----8<----
> > read_timeout () {
> >     saved_traps="$(trap)"
> 
> This does not work in dash, it always returns an empty string because
> trap is evaluated in a subshell.
> 
> Some other ash variants do not evaluate most command substitutions
> containing only a single builtin in a subshell, but this was removed in
> NetBSD sh and dash because such commands can affect the shell in wrong
> ways (e.g. $(exit 1) causes FreeBSD sh to exit).

POSIX:2008 lists

save_traps=$(trap)
...
eval "$save_traps"

as an example in the specification of the trap special builtin,
although it somewhat contradicts the description. This goes back
to at lease the SUSv2 in 1997 and it currently works e.g. in bash
and ksh93.

> A recent or proposed POSIX interpretation has said that $(trap) should
> work, and that this may be done by treating a lone trap command
> specially or by having trap in a subshell output the parent's traps
> until a trap has been set in the subshell. To help the former case,
> stuff like TRAP=trap; y=$($TRAP) is not required to work.
> 
> A problem in the script is that it does not handle TERM set to the
> default action properly, as this is not included in trap's output.

Right, the following interpretation has been approved last year (see
http://austingroupbugs.net/view.php?id=53):
"When a subshell is entered, traps that are not being ignored shall
be set to the default actions, except in the case of a command
substitution containing only a single trap command, when the traps
need not be altered. Implementations may check for this case
using only lexical analysis; for example if `trap` and $( trap -- )
do not alter the traps in the subshell, cases such as assigning
var=trap and then using $($var) may still alter them."
and
"The trap command with no operands shall write to standard output
a list of commands associated with each condition. If the command
is executed in a subshell, the implementation does not perform
the optional check described above for a command substitution
containing only a single trap command, and no trap commands with
operands have been executed since entry to the subshell, the list
shall contain the commands that were associated with each
condition immediately before the subshell environment was entered.
Otherwise, the list shall contain the commands currently
associated with each condition."

So this IMHO this should be implemented as a special case in dash
as well.

> >     trap 'printf "timed out\n"; eval "${saved_traps}"; return' TERM
> >     ( sleep $1; kill -TERM $$ ) >/dev/null 2>&1 &
> 
> For portability, I recommend braces
>     { sleep $1; kill -TERM $$; } >/dev/null 2>&1 &
> 
> Some shells do not treat a background subshell specially and fork twice,
> which would cause the wrong process to be killed below.

Thanks for the hint.

> >     timer_pid=$!
> >     read $2
> >     kill $timer_pid 2>/dev/null
> 
> eval "${saved_traps}"  is missing here.

Yep, forgot that.

-- 
Guido Berhoerster
--
To unsubscribe from this list: send the line "unsubscribe dash" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [LARTC]     [Bugtraq]     [Yosemite Forum]     [Photo]

  Powered by Linux