zsh-workers
 help / color / mirror / code / Atom feed
* 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).