bug-bash
[Top][All Lists]
Advanced

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

Re: feature request: new builtin `defer`, scope delayed eval


From: Cynthia Coan
Subject: Re: feature request: new builtin `defer`, scope delayed eval
Date: Sat, 8 Oct 2022 00:56:35 -0600

Hi Koichi,

I'm well aware that "defer"/"safe trap appending" can be implemented
today as it stands (see the original email in this chain, which links
to an example that I've used in a more reduced form). I also have in
the past written several helpers for safely appending to a trap (yours
in particular can mess up with certain quoting rules, but is nothing a
quick sed can't fix). The latest example for this was effectively a
joke project I did (so not really fully complete, expect bugs, etc.),
but also shows more complex forms I've done, in the past:
https://raw.githubusercontent.com/Mythra/typeish/trunk/pkg/trap.sh ,
https://raw.githubusercontent.com/Mythra/typeish/trunk/pkg/defer.sh .
It was writing things of this nature in enough projects that actually
brought forth this proposal.

I don't see any particular criticisms about either `defer` as a
built-in, or adding functionality to `trap` outlined in particular.
In fact some of the things you mentioned you can do today, are also
outlined in the original email as things that can be "harder than they
need to be" (mostly talking about the want to colocate cleanup with
creation, rather than splitting it into another function for easier
readability when cleanup actions are very multi-stepped).

As such I can only guess that either:

  - you were trying to inform the list that it is possible. which I
appreciate! I know my original email left only a simple example, and
didn't delve into the other areas we now are talking about like traps.
  - or that because it is possible means we should not work at
improving this functionality at all. To which I would mention the fact
that we've added things like `local` which could also be implemented
with `RETURN` traps, I do not think we should use it as a blocker as a
reason itself, personally.

Thanks,
Cynthia

On Sat, Oct 8, 2022 at 12:11 AM Koichi Murase <myoga.murase@gmail.com> wrote:
>
> 2022年10月8日(土) 12:04 Cynthia Coan <cynthia@coan.dev>:
> > [...]
> >
> > Otherwise, I think we can perhaps reword this into two smaller
> > features: "function local trap signals",
>
> The existing RETURN trap is exactly the trap that can be used to clean
> up resources local to functions and is already ``function-local''
> unless the user changes its behavior by setting `declare -ft', `set
> -T', or `shopt -s extdebug'. One thing to note is that the RETURN trap
> should be cleaned up inside the RETURN trap itself by running `trap -
> RETURN', or otherwise the RETURN trap is erroneously considered by
> Bash to be set for the caller function.
>
> > and "options to safely
> > append/prepend to a trap" (for some definition of 'safe', perhaps this
> > just means separating by ';'?
>
> Currently, there is no way to register multiple handlers to a trap in
> a safe way, but if you can accept the approach by `;' or newline, you
> can just do it by getting the current trap string with `trap -p
> RETURN' and then overwrite the trap with the adjusted trap string. If
> you don't want to write such a code every time, you can write a shell
> function to perform that. In that case, be careful that the function
> needs to be marked with the trace attribute by ``declare -ft
> <function-name>''. Also, the RETURN trap needs to be suppressed for
> such a function itself. I haven't really tested it but something like
> this should work as you expect:
>
> function defer {
>   local command=$1 trap
>   eval "trap=($(trap -p RETURN))"
>   if [[ $trap ]]; then
>     trap[2]=$command$'\n'${trap[2]}
>   else
>     trap=(trap -- "$command" RETURN)
>   fi
>   trap[2]='if [[ $FUNCNAME != defer ]]; then '${trap[2]}$'\ntrap - RETURN\nfi'
>   "${trap[@]}"
> }
> declare -ft defer
>
> The above `defer' function effectively "eval"s the first argument
> through `trap', so you need to specify in the following way:
>
> defer 'rm -r "${tmp_dir}"'
> defer 'set +e'
> defer 'set +o pipefail'
>
> Another thing to note is that the RETURN trap will be skipped when
> Bash receives SIGINT, so if you want to properly perform the clean up
> even when your Bash program receives SIGINT, you need to additionally
> set the SIGINT handler in a proper way.
>
> --
> Koichi



reply via email to

[Prev in Thread] Current Thread [Next in Thread]