* Zsh does not follow POSIX when return is called during the action of a trap
@ 2014-03-12 15:36 Eduardo A. Bustamante López
2014-03-12 16:52 ` Bart Schaefer
0 siblings, 1 reply; 6+ messages in thread
From: Eduardo A. Bustamante López @ 2014-03-12 15:36 UTC (permalink / raw)
To: zsh-workers
Hi! I first reported this bug to bug-bash, but since it also applies
to zsh, I wanted you to know about it. I'll use the same report I
sent, since it's the same problem:
According to POSIX:
| The value of the special parameter '?' shall be set to n, an
| unsigned decimal integer, or to the exit status of the last command
| executed if n is not specified. If the value of n is greater than
| 255, the results are undefined. When return is executed in a trap
| action, the last command is considered to be the command that
| executed immediately preceding the trap action.
Source (EXIT STATUS section):
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#return
So, what I understand from this:
(1) When return is called without a numeric argument, the code
returned is that of the `last command'.
(2) The `last command' is defined as: ``[...] the command that
executed immediately preceding the trap action''.
Taking the SYNOPSIS for the trap builtin:
| trap n [condition...]
| trap [action condition...]
and from DESCRIPTION:
| Each time trap is invoked, the action argument shall be processed in
| a manner equivalent to:
|
| eval action
Source:
http://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#trap
So as I read it, `action' refers to the whole string.
Now, this means, taking the following pseudo-code:
| trap '(exit BEFORE-RETURN); return' SIGNAL
|
| fn() {
| (exit BEFORE-ACTION); -block here waiting for signal-
| }
If that script receives SIGNAL, it should return the BEFORE-ACTION
exit code, and not the BEFORE-RETURN exit code.
Testing this is a bit tricky, because there's no simple way of
blocking to wait for a signal in a way that it doesn't affect our
testing, so the bes I could come up with is this:
### begin test script
code='trap "(exit 2); return" USR1
f() {
{ echo; kill -USR1 $$; } | exit 3
return 5
}
(exit 7); f
'
shells=(
bash
'bash --posix'
ksh
mksh
dash
'busybox sh'
zsh
jsh
)
for attempt in {1..1000}; do
for shell in "address@hidden"; do
printf '%s: %s\n' "$shell" "$($shell -c "$code"; echo $?)"
done
done | sort | uniq -c
### end test script
And sample output from this script:
969 bash: 2
31 bash: 5
979 bash --posix: 2
21 bash --posix: 5
1000 busybox sh: 5
971 dash: 3
29 dash: 5
118 jsh: 3
882 jsh: 5
1 ksh: 0
999 ksh: 3
970 mksh: 3
30 mksh: 5
6 zsh: 2
994 zsh: 3
Most of the time, zsh returns the correct code (3, BEFORE-ACTION),
but sometimes it returns 2, which is BEFORE-RETURN (and it should not).
The versions tested are:
bash --version|head -n1:
GNU bash, version 4.3.0(2)-release (x86_64-unknown-linux-gnu)
zsh --version|head -n1:
zsh 4.3.17 (x86_64-unknown-linux-gnu)
ksh --version|head -n1:
version sh (AT&T Research) 93u+ 2012-02-29
mksh -c 'echo "$KSH_VERSION"':
@(#)MIRBSD KSH R40 2012/07/20 Debian-7
apt-cache policy dash|grep Installed:
Installed: 0.5.7-3
apt-cache policy busybox|grep Installed:
Installed: 1:1.20.0-7
head -n3 ~/local/src/heirloom-sh/CHANGES:
Release ...
* A bug in the supplied realloc() replacement could result in heap
corruption. (No resulting failures have been observed with sh so far.)
Original bug report:
http://lists.gnu.org/archive/html/bug-bash/2014-03/msg00053.html
--
Eduardo Alan Bustamante López
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Zsh does not follow POSIX when return is called during the action of a trap
2014-03-12 15:36 Zsh does not follow POSIX when return is called during the action of a trap Eduardo A. Bustamante López
@ 2014-03-12 16:52 ` Bart Schaefer
2014-03-12 17:03 ` Peter Stephenson
0 siblings, 1 reply; 6+ messages in thread
From: Bart Schaefer @ 2014-03-12 16:52 UTC (permalink / raw)
To: Eduardo A. Bustamante Lopez, zsh-workers
On Mar 12, 8:36am, Eduardo A. Bustamante Lopez wrote:
}
} Hi! I first reported this bug to bug-bash, but since it also applies
} to zsh, I wanted you to know about it.
Have you tried this with the POSIX_TRAPS option set?
Zsh does not in general conform to POSIX at all unless you run it with
the appropriate compatibility settings.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Zsh does not follow POSIX when return is called during the action of a trap
2014-03-12 16:52 ` Bart Schaefer
@ 2014-03-12 17:03 ` Peter Stephenson
2014-03-12 17:47 ` Eduardo A. Bustamante López
2014-03-12 17:49 ` Chet Ramey
0 siblings, 2 replies; 6+ messages in thread
From: Peter Stephenson @ 2014-03-12 17:03 UTC (permalink / raw)
To: zsh-workers; +Cc: Eduardo A. Bustamante Lopez
On Wed, 12 Mar 2014 09:52:10 -0700
Bart Schaefer <schaefer@brasslantern.com> wrote:
> On Mar 12, 8:36am, Eduardo A. Bustamante Lopez wrote:
> }
> } Hi! I first reported this bug to bug-bash, but since it also applies
> } to zsh, I wanted you to know about it.
>
> Have you tried this with the POSIX_TRAPS option set?
>
> Zsh does not in general conform to POSIX at all unless you run it with
> the appropriate compatibility settings.
I was going to mention that. I think it still needs some work --- which
I know how to do in this case. N.B. you can test this with the line
[ x$ZSH_VERSION != x ] && emulate sh
at the top of the "code" variable.
However, I'm trying to work out what happens with the case
| trap '(exit BEFORE-RETURN); return EXPLICIT-RETURN-VALUE' SIGNAL
|
| fn() {
| (exit BEFORE-ACTION); -block here waiting for signal-
| }
Should this exit with EXPLICIT-RETURN_VALUE or BEFORE-ACTION? The
latter is easier to implement but my guess (without ploughing through
the standard) is EXPLICIT-RETURN-VALUE is right here.
pws
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Zsh does not follow POSIX when return is called during the action of a trap
2014-03-12 17:03 ` Peter Stephenson
@ 2014-03-12 17:47 ` Eduardo A. Bustamante López
2014-03-12 17:49 ` Chet Ramey
1 sibling, 0 replies; 6+ messages in thread
From: Eduardo A. Bustamante López @ 2014-03-12 17:47 UTC (permalink / raw)
To: Peter Stephenson; +Cc: zsh-workers
On Wed, Mar 12, 2014 at 05:03:09PM +0000, Peter Stephenson wrote:
> On Wed, 12 Mar 2014 09:52:10 -0700
> Bart Schaefer <schaefer@brasslantern.com> wrote:
> > Have you tried this with the POSIX_TRAPS option set?
> >
> > Zsh does not in general conform to POSIX at all unless you run it with
> > the appropriate compatibility settings.
I see. Well, I now ran the code with 'emulate sh' (thanks Peter, for
the suggestion).
These are the results:
| 12 zsh: 2
| 988 zsh: 3
| zsh 5.0.5-dev-0 (x86_64-unknown-linux-gnu)
For this new code:
| code='
| emulate sh
|
| trap "(exit 2); return" USR1
| f() {
| { echo; kill -USR1 $$; } | exit 3
| return 5
| }
|
| (exit 7); f
| '
|
| shells=(
| zsh
| )
|
| for attempt in {1..1000}; do
| for shell in "${shells[@]}"; do
| printf '%s: %s\n' "$shell" "$($shell -c "$code"; echo $?)"
| done
| done | sort | uniq -c
|
| zsh --version
> However, I'm trying to work out what happens with the case
>
> | trap '(exit BEFORE-RETURN); return EXPLICIT-RETURN-VALUE' SIGNAL
> |
> | fn() {
> | (exit BEFORE-ACTION); -block here waiting for signal-
> | }
>
> Should this exit with EXPLICIT-RETURN_VALUE or BEFORE-ACTION? The
> latter is easier to implement but my guess (without ploughing through
> the standard) is EXPLICIT-RETURN-VALUE is right here.
>
> pws
>
Ah, I see. I tested with this:
| code='
| emulate sh
|
| trap "(exit 2); return 9" USR1
| f() {
| { echo; kill -USR1 $$; } | exit 3
| return 5
| }
|
| (exit 7); f
| '
|
| shells=(
| zsh
| )
|
| for attempt in {1..1000}; do
| for shell in "${shells[@]}"; do
| printf '%s: %s\n' "$shell" "$($shell -c "$code"; echo $?)"
| done
| done | sort | uniq -c
|
| zsh --version
And got:
| 991 zsh: 3
| 9 zsh: 9
| zsh 5.0.5-dev-0 (x86_64-unknown-linux-gnu)
Which is kind of wrong, since it should always be 9, but according to
the results, it's mostly 3. POSIX states:
| The value of the special parameter '?' shall be set to n, an unsigned
| decimal integer, or to the exit status of the last command executed if n is
| not specified. If the value of n is greater than 255, the results are
| undefined. When return is executed in a trap action, the last command is
| considered to be the command that executed immediately preceding the trap
| action.
So, the result should be 9 ("'?' shall be set to n [...] or the exit
status of the last command [...]"). Because in this case 'n' is set.
--
Eduardo Alan Bustamante López
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Zsh does not follow POSIX when return is called during the action of a trap
2014-03-12 17:03 ` Peter Stephenson
2014-03-12 17:47 ` Eduardo A. Bustamante López
@ 2014-03-12 17:49 ` Chet Ramey
2014-03-12 18:23 ` Peter Stephenson
1 sibling, 1 reply; 6+ messages in thread
From: Chet Ramey @ 2014-03-12 17:49 UTC (permalink / raw)
To: Peter Stephenson, zsh-workers; +Cc: chet.ramey, Eduardo A. Bustamante Lopez
On 3/12/14 1:03 PM, Peter Stephenson wrote:
> However, I'm trying to work out what happens with the case
>
> | trap '(exit BEFORE-RETURN); return EXPLICIT-RETURN-VALUE' SIGNAL
> |
> | fn() {
> | (exit BEFORE-ACTION); -block here waiting for signal-
> | }
>
> Should this exit with EXPLICIT-RETURN_VALUE or BEFORE-ACTION? The
> latter is easier to implement but my guess (without ploughing through
> the standard) is EXPLICIT-RETURN-VALUE is right here.
The correct exit value is EXPLICIT-RETURN-VALUE.
The standards text that Eduardo quoted only applies to the case where
`return' is not given an argument.
--
``The lyf so short, the craft so long to lerne.'' - Chaucer
``Ars longa, vita brevis'' - Hippocrates
Chet Ramey, ITS, CWRU chet@case.edu http://cnswww.cns.cwru.edu/~chet/
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: Zsh does not follow POSIX when return is called during the action of a trap
2014-03-12 17:49 ` Chet Ramey
@ 2014-03-12 18:23 ` Peter Stephenson
0 siblings, 0 replies; 6+ messages in thread
From: Peter Stephenson @ 2014-03-12 18:23 UTC (permalink / raw)
To: zsh-workers; +Cc: Eduardo A. Bustamante Lopez
On Wed, 12 Mar 2014 13:49:18 -0400
Chet Ramey <chet.ramey@case.edu> wrote:
> On 3/12/14 1:03 PM, Peter Stephenson wrote:
>
> > However, I'm trying to work out what happens with the case
> >
> > | trap '(exit BEFORE-RETURN); return EXPLICIT-RETURN-VALUE' SIGNAL
> > |
> > | fn() {
> > | (exit BEFORE-ACTION); -block here waiting for signal-
> > | }
> >
> > Should this exit with EXPLICIT-RETURN_VALUE or BEFORE-ACTION? The
> > latter is easier to implement but my guess (without ploughing through
> > the standard) is EXPLICIT-RETURN-VALUE is right here.
>
> The correct exit value is EXPLICIT-RETURN-VALUE.
OK, so I think the answer is as follows... I'm out of time, I'll give
it a check with explicit return values tomorrow.
I'll also add some additional documentation for POSIX_TRAPS.
diff --git a/Src/builtin.c b/Src/builtin.c
index 9bcbcf7..0419c39 100644
--- a/Src/builtin.c
+++ b/Src/builtin.c
@@ -4688,9 +4688,10 @@ exit_pending;
int
bin_break(char *name, char **argv, UNUSED(Options ops), int func)
{
- int num = lastval, nump = 0;
+ int num = lastval, nump = 0, implicit;
/* handle one optional numeric argument */
+ implicit = !*argv;
if (*argv) {
num = mathevali(*argv++);
nump = 1;
@@ -4721,7 +4722,12 @@ bin_break(char *name, char **argv, UNUSED(Options ops), int func)
retflag = 1;
breaks = loops;
lastval = num;
- if (trap_state == TRAP_STATE_PRIMED && trap_return == -2) {
+ if (trap_state == TRAP_STATE_PRIMED && trap_return == -2 &&
+ /*
+ * With POSIX, "return" on its own in a trap doesn't
+ * update $? --- we keep the status from before the trap.
+ */
+ !(isset(POSIXTRAPS) && implicit)) {
trap_state = TRAP_STATE_FORCE_RETURN;
trap_return = lastval;
}
diff --git a/Src/signals.c b/Src/signals.c
index c8f5fbc..a6eb803 100644
--- a/Src/signals.c
+++ b/Src/signals.c
@@ -1155,6 +1155,7 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
char *name, num[4];
int obreaks = breaks;
int oretflag = retflag;
+ int olastval = lastval;
int isfunc;
int traperr, new_trap_state, new_trap_return;
@@ -1261,6 +1262,13 @@ dotrapargs(int sig, int *sigtr, void *sigfn)
} else {
if (traperr && !EMULATION(EMULATE_SH))
lastval = 1;
+ else {
+ /*
+ * With no explicit forced return, we keep the
+ * lastval from before the trap ran.
+ */
+ lastval = olastval;
+ }
if (try_tryflag)
errflag = traperr;
breaks += obreaks;
pws
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2014-03-12 18:33 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-03-12 15:36 Zsh does not follow POSIX when return is called during the action of a trap Eduardo A. Bustamante López
2014-03-12 16:52 ` Bart Schaefer
2014-03-12 17:03 ` Peter Stephenson
2014-03-12 17:47 ` Eduardo A. Bustamante López
2014-03-12 17:49 ` Chet Ramey
2014-03-12 18:23 ` Peter Stephenson
Code repositories for project(s) associated with this public inbox
https://git.vuxu.org/mirror/zsh/
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).