help-bash
[Top][All Lists]
Advanced

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

Re: [Question] Reliable way to clean up a directory in EXIT trap


From: Masahiro Yamada
Subject: Re: [Question] Reliable way to clean up a directory in EXIT trap
Date: Thu, 28 Jul 2022 15:49:09 +0900

On Thu, Jul 21, 2022 at 7:49 AM Koichi Murase <myoga.murase@gmail.com> wrote:
>
> 2022年7月20日(水) 13:20 Masahiro Yamada <masahiroy@kernel.org>:
> > If Bash receives SIGINT while executing the EXIT trap,
> > it will run the command 'echo ouch', but never return
> > to the point where it was interrupted.
> >
> > This is different from how interrupt handlers are processed.
>
> What does "the point where it was interrupted" mean? If I literally
> read it, it doesn't seem to be correct as far as I try.
>
> $ bash -c 'trapint() { echo INT; }; trap trapint INT; trapexit() {
> echo EXIT1; sleep 3; echo EXIT2; }; trap trapexit EXIT; exit'
> EXIT1
> ^CINT
> EXIT2
>
> > I think Bash can improve this point:
> > The EXIT handler should not be interrupted by any signal.
>
> I don't think it makes sense. If all the signals are disabled in
> running the EXIT handler, there is no way to stop the EXIT handler
> when it hangs other than sending SIGKILL. Even if you might see this
> useful for your case, I hardly think it should be the default.


Sorry, you are right.

If bash is interrupted, it will resume from the next command.

If the example above, 'sleep 3' is interrupted,
and bash will run 'echo EXIT2'.





Now, I understood your previous sample code:

for i in {0..999}; do
  (
    tmp=$BASHPID.tmp
    cleanup() { rm -rf "$tmp"; }
    trapint() { cleanup; trap - INT; kill -INT "$BASHPID"; }
    trap cleanup EXIT
    trap trapint INT
    >> "$tmp"
  )
done


If "rm -rf $tmp" is interrupted while EXIT trap is being executed,
we cannot clean up the tmp directory.

But, bash will trigger trapint(), where we have the second chance
to do "rm -rf $tmp".

So, the key point is that we need to call the second "rm -rf $tmp" somehow
in case the first "rm -rf $tmp".






Here is another sample code.
This also seems to clean up the tmp directory.

for i in {0..999}; do
  (
    tmp=$BASHPID.tmp
    cleanup() { rm -rf "$tmp"; rm -rf "$tmp"; }
    trap cleanup EXIT
    >> "$tmp"
    trap : INT
  )
done

This approach completely blocks SIGINT, so
WIFSIGNALED from wait() status will not be
propagated to the caller, though.





--
Best Regards
Masahiro Yamada



reply via email to

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