Re: XCU 2.14: Exit status by no-argument `return' in shell trap handlers

2020-04-20 Thread Koichi Murase
2020-04-20 1:42 Robert Elz :
> Probably not, bosh is derived from that shell (more or less) and it is
> also A
>
> [...]
>
> So are the FreeBSD and NetBSD shells (which is not surprising, as like
> dash, they're descendants of ash).
>
> You can also add zsh to A:

Thank you for the information.  I have also tested ksh93, pdksh and
oksh (OpenBSD KornShell) on FreeBSD.  `ksh93' is (B), and `pdksh' and
`oksh' do not implement the special treatment in trap handlers.  Here
is the current list:

  (A) zsh (zsh-5.7.1, zsh-5.6.2)
ash variants (dash-0.5.10.2, busybox-1.28.3, FreeBSD sh, NetBSD sh),
Bourne sh variants (heirloom-sh-050706-4, bosh-2020/04/18)
  (B) bash-4.4, gwsh,
ksh variants (ksh-2020.0.0, ksh93.u_1, mksh-R57, mksh-R56)
  (C) yash-2.49
  (D) none
  (Not Implemented) bash-4.3, pdksh-5.2.14.2, oksh-6.6.1, posh-0.13.2

I think now it is rather clear that the current wording of POSIX is
somehow ambiguous and there can be different interpretations.  In
fact, there is a split, (A) vs (B), in shell implementations.

>> 2020-04-19 23:00 Harald van Dijk :
>>> It does still mean that anyone writing a function needs to beware that
>>> exit and exit $? do not have the same effect, if there is any
>>> possibility that the function will be invoked from a trap action. I
>>> suspect most people writing functions will not be aware of that.

Yes, that is the problem.  Actually, the original problem is that I
just want to perform `eval "$PROMPT_COMMAND"` in a trap action in Bash
script where `$PROMPT_COMMAND' is provided by users.  If everything
is under the control, I can just always write `return $?', but the
commands in `$PROMPT_COMMAND' are specified by users who are unlikely
to care about this problem.  This specific case is just my personal
one, but I think the behavior (B) can possibly cause similar problems
in other shell scripts in general.

>> 2020-04-19 20:51 Robert Elz :
>>> [...]
>>>
>>> The end result, unless we can get agreement that some
>>> implementations are buggy, and will be fixed (which given the
>>> split seems an unlikely outcome) is likely to simply be that all
>>> of this simply becomes unspecified (or perhaps we could hope,
>>> implementation defined) which will mean even more cases where it
>>> becomes more difficult to write portable reliable code.
>>>
>>> kre

>> 2020-04-19 23:00 Harald van Dijk :
>>> True, and if the intent is that exit and return behave differently
>>> and the standard is updated to clearly require that, I have no
>>> problem changing the shell back to the prior behaviour.

According to these comments, it seems like a deadlock. The standard
will not change until shells change their behavior to match with each
other, and shells will not change their behavior until the standard is
clarified.  Actually I can understand both sides, but I think we can
find a point of compromise.

There are already different implementations so it is already difficult
to write portable and reliable code.  Even some shells such as
`pdksh', `oksh' and `posh' do not implement the special behavior of
`return' in trap actions at all, so the standard does not describe the
current situation properly.  Thus I think the side effect of making it
unspecified is limited.  Maybe we can first let it be unspecified and
then wait to see whether the shells will switch the behavior from the
literal reading (B) to more sensible interpretation (A) or not.

- It might be difficult to change the behavior (B) of `ksh' and `mksh'
  because its behavior is unchanged at least since 1993.

- While, `bash' implemented the behavior (B) in bash-4.4 which is
  relatively recently in its long history, so maybe we can hope for a
  change.

- Harald: The remaining shell with (B) in the list is `gwsh'.  For
  example, if the standard changes its description to `unspecified'
  (instead of clearly requiring (A) or other interpretation), do you
  think you have a chance to change the behavior back?

- I think `yash' with the interpretation (C) will follow the standard
  anytime if the standard clarifies the intended behavior because
  `yash' aims to strictly support POSIX.

Thank you.

--
Koichi



Re: XCU 2.14: Exit status by no-argument `return' in shell trap handlers

2020-04-19 Thread Robert Elz
Date:Sun, 19 Apr 2020 22:02:49 +0900
From:Koichi Murase 
Message-ID:  


  | Thank you for pointing out this.  After reading your comment, I was
  | interested in the behavior of the Bourne shell, so I have tried with
  | the Heirloom Bourne shell (which is a port of the SVR4 Bourne shell
  | according to its page) in AUR.  Actually, the Heirloom Bourne shell
  | turns out to follow the interpretation (A) [ although it might be
  | possible that the behavior is changed by the port ].

Probably not, bosh is derived from that shell (more or less) and it is
also A

bosh $ $SHELL /tmp/TTT
In trap argument: last command preceding the trap action
In direct function call: last command in the trap action
In indirect function call: last command in the trap action
bosh $ $SHELL -c 'echo ${.sh.version}'
version bosh 2020/04/10 a+ (amd64-unknown-netbsd8.99.30)

(it is really version 2020/04/18 without the version string being updated).

So are the FreeBSD and NetBSD shells (which is not surprising, as like
dash, they're descendants of ash).

You can also add zsh to A:

zsh $ $SHELL /tmp/TTT
In trap argument: last command preceding the trap action
In direct function call: last command in the trap action
In indirect function call: last command in the trap action
zsh $ echo $SHELL
/usr/pkg/bin/zsh
zsh $ $SHELL -c 'echo ${ZSH_VERSION}'
5.6.2

(/tmp/TTT is your script - but with a newline removed.  It might have just
been an e-mail artifact, and was in the middle of one of the messages).

  | Thank you for suggesting another possibility.  Let me call the above
  | one the interpretation (D).
  | But there was actually no implementation that follows (D)

I am not all that surprised, it would be a rather bizarre interpretation.

kre



Re: XCU 2.14: Exit status by no-argument `return' in shell trap handlers

2020-04-19 Thread Harald van Dijk

On 19/04/2020 14:32, Koichi Murase wrote:

2020-04-19 21:55 Harald van Dijk :

My reading was that interpretation B must be what is intended, which
is why I had modified my shell, a fork of dash, to change dash's A
behaviour to B in late 2018.


Thank you.  Is your shell this https://github.com/hvdijk/gwsh ?  I
tried gwsh-0.5.9.1.  Here is the updated list:


Yes, that is my shell. Pay no attention to that version number, that is 
dash's version number that I have not updated because I never did a 
proper release yet. :)



   (A) `zsh', `dash', `busybox', `heirloom-sh'
   (B) `bash-4.4', `mksh', `ksh', `gwsh'
   (C) `yash'
   (D) none
   Not Implemented: `bash-4.3', `posh'


My reasoning for that is that the description of the return
commanhd ("When return is executed in a trap action, the last
command is considered to be the command that executed immediately
preceding the trap action.") is identical to that of the exit
command ("When exit is executed in a trap action, the last command
is considered to be the command that executed immediately preceding
the trap action.")


Thank you.  This is a good point. Maybe this is the origin of the
current wording.


and for the exit command, almost all shells, including dash, are in
agreement that it applies even when the exit command is invoked
indirectly. [...]


It is reasonable that indirect `exit' in function calls in trap
handlers are affected because it actually brings the completion of
trap action which is more consistent with the following description of
`trap'.  While, the trap action will not be completed by indirect
`return', so it is not surprising that the behavior can be different
between `exit' and `return'.


True, and if the intent is that exit and return behave differently and 
the standard is updated to clearly require that, I have no problem 
changing the shell back to the prior behaviour.


It does still mean that anyone writing a function needs to beware that 
exit and exit $? do not have the same effect, if there is any 
possibility that the function will be invoked from a trap action. I 
suspect most people writing functions will not be aware of that.


Another question is what the behaviour should be in a subshell. That is:

  f() { false; return; } # or exit
  trap '(f; echo $?)' EXIT

Is the return or exit here still considered to execute within a trap 
action, or does the fact that subshells reset traps mean that whatever 
was executing in the parent shell can no longer be considered a trap 
action within the subshell?


Cheers,
Harald van Dijk



Re: XCU 2.14: Exit status by no-argument `return' in shell trap handlers

2020-04-19 Thread Koichi Murase
2020-04-19 21:55 Harald van Dijk :
> My reading was that interpretation B must be what is intended, which
> is why I had modified my shell, a fork of dash, to change dash's A
> behaviour to B in late 2018.

Thank you.  Is your shell this https://github.com/hvdijk/gwsh ?  I
tried gwsh-0.5.9.1.  Here is the updated list:

  (A) `zsh', `dash', `busybox', `heirloom-sh'
  (B) `bash-4.4', `mksh', `ksh', `gwsh'
  (C) `yash'
  (D) none
  Not Implemented: `bash-4.3', `posh'

> My reasoning for that is that the description of the return
> commanhd ("When return is executed in a trap action, the last
> command is considered to be the command that executed immediately
> preceding the trap action.") is identical to that of the exit
> command ("When exit is executed in a trap action, the last command
> is considered to be the command that executed immediately preceding
> the trap action.")

Thank you.  This is a good point. Maybe this is the origin of the
current wording.

> and for the exit command, almost all shells, including dash, are in
> agreement that it applies even when the exit command is invoked
> indirectly. [...]

It is reasonable that indirect `exit' in function calls in trap
handlers are affected because it actually brings the completion of
trap action which is more consistent with the following description of
`trap'.  While, the trap action will not be completed by indirect
`return', so it is not surprising that the behavior can be different
between `exit' and `return'.

 [XCU 2.14 Special Built-In Utilities - trap - DESCRIPTION/paragraph 2]

 [...] The value of "$?" after the trap action completes shall be
 the value it had before trap was invoked.

--
Koichi



Re: XCU 2.14: Exit status by no-argument `return' in shell trap handlers

2020-04-19 Thread Koichi Murase
2020-04-19 20:51 Robert Elz :
> Before I make any other comments, I should point out that quite a
> bit of what is in the shell standard (and the rest of POSIX, and for
> that matter, many other standards) isn't there because there's a
> good reason for it, but just because the original shells implemented
> it that way, often for expediency purposes (the original Bourne
> shell had to run in the 64KB address space (code, data, and stack)
> of a PDP-11).

Thank you for pointing out this.  After reading your comment, I was
interested in the behavior of the Bourne shell, so I have tried with
the Heirloom Bourne shell (which is a port of the SVR4 Bourne shell
according to its page) in AUR.  Actually, the Heirloom Bourne shell
turns out to follow the interpretation (A) [ although it might be
possible that the behavior is changed by the port ].

2020-04-19 20:51 Robert Elz :
> Note that another intrepretation that you didn't list is that this
> magic return applies to return in functions called directly from the
> trap action string (which are more likely to be functions written
> expressly with the intent of being called this way) but not to
> functions called indirectly.

Thank you for suggesting another possibility.  Let me call the above
one the interpretation (D).  I have updated the script to distinguish
(D) from (B):

  setexit() { return "$1"; }
  invoke() { kill -USR1 $$; return 222; }

  trap 'setexit 111; return' USR1
  invoke
  case $? in
  0)   echo 'In trap argument: last command preceding the trap action' ;;
  111) echo 'In trap argument: last command in the trap action' ;;
  222) echo 'In trap argument: (failed to exit the function)' ;;
  *)   echo 'In trap argument: (unexpected)' ;;
  esac

  stat=99
  handler() { setexit 111; return; }
  trap 'handler; stat=$?; return' USR1
  invoke
  case $stat in
  0)   echo 'In direct function call: last command preceding the trap action' ;;
  111) echo 'In direct function call: last command in the trap action' ;;
  *)   echo 'In direct function call: (unexpected)' ;;
  esac

  stat=99
  utility2() { setexit 111; return; }
  handler2() { utility2; stat=$?; }
  trap 'handler2' USR1
  invoke
  case $stat in
  0)   echo 'In indirect function call: last command preceding the
trap action' ;;
  111) echo 'In indirect function call: last command in the trap action' ;;
  *)   echo 'In indirect function call: (unexpected)' ;;
  esac

But there was actually no implementation that follows (D) among the
shells that I tested so far.  Here is the updated list:

  (A) `zsh', `dash', `busybox', `heirloom-sh'
  (B) `bash-4.4', `mksh', `ksh'
  (C) `yash'
  (D) none
  Not Implemented: `bash-4.3', `posh'

--
Koichi



Re: XCU 2.14: Exit status by no-argument `return' in shell trap handlers

2020-04-19 Thread Robert Elz
Date:Sun, 19 Apr 2020 17:12:42 +0900
From:Koichi Murase 
Message-ID:  


  | Currently, I do not see any rationale for the behavior (B) or (C).

Before I make any other comments, I should point out that quite a bit
of what is in the shell standard (and the rest of POSIX, and for that
matter, many other standards) isn't there because there's a good reason
for it, but just because the original shells implemented it that way,
often for expediency purposes (the original Bourne shell had to run in
the 64KB address space (code, data, and stack) of a PDP-11).

So that's not really a meaningfull question to ask in this context,
the standard might very well require something totally irrational,
simply because that is how it has been implemented.

If something is implemented a particular way, applications (scripts)
may come to depend upon it, so changing it later can be difficult.

All that aside, I agree that the wording in the standard is ambiguous.

My first reading (my immediate impression) is that your interpretation A
is what is intended, and only a return command executing directly from the
trap action itself, and not one in a function that happens to be called,
should be affected.   (And of course, the former is only specified if the
trap occurs while running a function or dot script).

That is, with code like

long_func() {
t=$(trap -p)
trap 'eval "$T"; return' INT
while sleep 10
do
printf .
done
}

That is, it should not apply in functions called from a trap action,
for them, return should act just like it would in a function called
from any other source.

Note that another intrepretation that you didn't list is that this magic
return applies to return in functions called directly from the trap action
string (which are more likely to be functions written expressly with the
intent of being called this way) but not to functions called indirectly.

Next thing to note is that all of this wording is to be changed in the
next version of the standard - there's no longer any "exit status of the
last command" stuff for return (or exit), rather these are to be specified
to return the value of $? when no arg is given.

When we do that, all we need to do is specify how traps affect $?, which
should be (IMO), on entry, $? is the status of the last command (ie: starting
a trap action changes nothing wrt $? - it holds the same value it would have
had if there were no trap action called, and the next command simply started.

On return from a trap action to the command that would have been executed
next, had no trap action intervened, the exit status should be retained at
the same value it had before the trap action was executed (the trap should
not alter $?).

If a trap action causes the control flow to be altered (that is, by
executing a return/exit/break/continue outside of a context that is local
to the trap action) then the exit status should be whatever the trap
action causes to happen (that of the last command executed there).

But that I believe this is the most appropriate specification does not
mean that is what can go into the standard, that depends upon what the
implementations actually do - and as there seems to be a diversity of
implementations (including as to what is the command before the trap,
when the trap is caused by a kill ... and possibly for async signals as
well - some shells seem to use the status of the command before the kill
command as the relevant one (that would be the status of the last command
executed before the signal arrived), even though the standard is clear that
the trap action cannot be run while a foreground command is running.   Here
the trap cannot run before the kill command starts (it is that which sends
the signal) and assuming it is run in foreground, that means not until
after the kill command completes, which means $? should be the status from 
he kill command.   But some shells seem to run the trap action with $? being
the status of the commane before the kill command (which would be the
value of $? when the signal arrived).

The end result, unless we can get agreement that some implementations are
buggy, and will be fixed (which given the split seems an unlikely outcome)
is likely to simply be that all of this simply becomes unspecified (or
perhaps we could hope, implementation defined) which will mean even more
cases where it becomes more difficult to write portable reliable code.

kre





Re: XCU 2.14: Exit status by no-argument `return' in shell trap handlers

2020-04-19 Thread Oğuz
19 Nisan 2020 Pazar tarihinde Koichi Murase  yazdı:

> 2020-04-19 15:21 Oğuz :
> > The same document you linked says:
> >
> > > If the shell is not currently executing a function or dot script, the
> > > results are unspecified.
> >
> > in DESCRIPTION section; it's unspecified what those returns do.
>
> Thank you for the comment, but I am confused.  In both two examples
> that I provided, it actually running a function when `kill' is called,
> i.e. `kill' is called when `invoke' is executed.  Then the trap
> handler is invoked while executing the function.
>
>
So was I, obviously overlooked that part.


> If that is not the correct interpretation [i.e., the function is not
> considered currently executed while the trap handler is processed, and
> the description on `return' applies only to `return's appearing in the
> function calls inside the trap action], then it is the third
> interpretation:
>
> (C) The `return's in the function-call tree in trap processing are
>   affected, but the behavior of `return' directly called from the trap
>   argument is unspecified.
>
> However, in this case, the same question for the interpretation (B)
> also applies to the interpretation (C):
>
> 2020-04-19 13:32 Koichi Murase :
> > > - If the literal interpretation (B) is correct, what is the use case
> > >   of this behavior, or what is the rationale for this behavior?
>
> Currently, I do not see any rationale for the behavior (B) or (C).
> Does anyone know something which explains the necessity of the
> behavior (B) or (C)?
>
> 2020-04-19 15:21 Oğuz :
> > However some shells (dash for instance) print 42. I think it's a
> > misreading of the standard.
>
> It seems to me that (A) is the natural behavior because it is more
> consistent with the following description in `trap' section.  I can
> imagine that the special case for the `return' exit status is added to
> make it more consistent with this section:
>
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V
> 3_chap02.html#tag_18_28_03
> > [XCU 2.14 Special Built-In Utilities - trap - DESCRIPTION/paragraph 2]
> >
> > [...] The value of "$?" after the trap action completes shall be the
> value
> > it had before trap was invoked.


Apparently in trap actions return without an operand is reserved for
retaining exit status of the last command preceding the trap action. Thus
(B) sounds like the correct interpretation. However this way functions
invoked from trap actions have to use return $? to deliver exit status of
the last command they executed.

I agree that the standard should elaborate on this.

Maybe I am wrong, but I cannot stop suspecting that this is a wording
> problem that the original intension is (A), but it just reads like (B)
> or (C) due to not enough description in the standard.
>
> --
> Koichi
>



-- 
Oğuz


Re: XCU 2.14: Exit status by no-argument `return' in shell trap handlers

2020-04-19 Thread Koichi Murase
2020-04-19 15:21 Oğuz :
> The same document you linked says:
>
> > If the shell is not currently executing a function or dot script, the
> > results are unspecified.
>
> in DESCRIPTION section; it's unspecified what those returns do.

Thank you for the comment, but I am confused.  In both two examples
that I provided, it actually running a function when `kill' is called,
i.e. `kill' is called when `invoke' is executed.  Then the trap
handler is invoked while executing the function.

If that is not the correct interpretation [i.e., the function is not
considered currently executed while the trap handler is processed, and
the description on `return' applies only to `return's appearing in the
function calls inside the trap action], then it is the third
interpretation:

(C) The `return's in the function-call tree in trap processing are
  affected, but the behavior of `return' directly called from the trap
  argument is unspecified.

However, in this case, the same question for the interpretation (B)
also applies to the interpretation (C):

2020-04-19 13:32 Koichi Murase :
> > - If the literal interpretation (B) is correct, what is the use case
> >   of this behavior, or what is the rationale for this behavior?

Currently, I do not see any rationale for the behavior (B) or (C).
Does anyone know something which explains the necessity of the
behavior (B) or (C)?

2020-04-19 15:21 Oğuz :
> However some shells (dash for instance) print 42. I think it's a
> misreading of the standard.

It seems to me that (A) is the natural behavior because it is more
consistent with the following description in `trap' section.  I can
imagine that the special case for the `return' exit status is added to
make it more consistent with this section:

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_28_03
> [XCU 2.14 Special Built-In Utilities - trap - DESCRIPTION/paragraph 2]
>
> [...] The value of "$?" after the trap action completes shall be the value
> it had before trap was invoked.

Maybe I am wrong, but I cannot stop suspecting that this is a wording
problem that the original intension is (A), but it just reads like (B)
or (C) due to not enough description in the standard.

--
Koichi



Re: XCU 2.14: Exit status by no-argument `return' in shell trap handlers

2020-04-19 Thread Oğuz
Oh, sorry. It should be

g() { f; return; }

not

g() { return; }

On Sun, Apr 19, 2020 at 9:20 AM Oğuz  wrote:
>
> > I have a question on the POSIX behavior of `return' shell builtin
> > without arguments when used in a shell `trap' action.
> > [...]
> > trap 'setexit 111; return' USR1
> > [...]
> > trap 'handler; stat=$?; return' USR1
>
> The same document you linked says:
>
> > If the shell is not currently executing a function or dot script, the
> > results are unspecified.
>
> in DESCRIPTION section; it's unspecified what those returns do.
>
> I got what you're actually asking though. According to the
> standard, application below should print kill's exit status bacause
> it is *the command that executed immediately preceding the trap
> action*.
>
> f() { return 42; }
> g() { return; }
> trap 'g; echo $?' USR1
> kill -USR1 $$
>
> However some shells (dash for instance) print 42. I think it's a
> misreading of the standard.
>
> --
> Oğuz



-- 
Oğuz



Re: XCU 2.14: Exit status by no-argument `return' in shell trap handlers

2020-04-19 Thread Oğuz
> I have a question on the POSIX behavior of `return' shell builtin
> without arguments when used in a shell `trap' action.
> [...]
> trap 'setexit 111; return' USR1
> [...]
> trap 'handler; stat=$?; return' USR1

The same document you linked says:

> If the shell is not currently executing a function or dot script, the
> results are unspecified.

in DESCRIPTION section; it's unspecified what those returns do.

I got what you're actually asking though. According to the
standard, application below should print kill's exit status bacause
it is *the command that executed immediately preceding the trap
action*.

f() { return 42; }
g() { return; }
trap 'g; echo $?' USR1
kill -USR1 $$

However some shells (dash for instance) print 42. I think it's a
misreading of the standard.

-- 
Oğuz