[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