#!/bin/sh --
for set_trap_sig in HUP INT QUIT ALRM TERM; do
trap -- '
trap -- - '"${set_trap_sig:?}"' EXIT || exit "$?"
kill -s '"${set_trap_sig:?}"' -- "$$" || exit "$?"' "$set_trap_sig"
done
sleep 15 || exit "$?"
SIGINTをスクリプトに送信すると、これが発生します。
user@hostname:/tmp$ ./script.sh
^C./script.sh: 3: ./script.sh: Syntax error: EOF in backquote substitution
この質問はダッシュにのみ当てはまるようです。 ash、bash、ksh93ではこのエラーは発生しません。私のスクリプトにバックティック文字も含まれていないので、これは特に奇妙です。
5行目の末尾から二重引用符を削除すると、$?
エラーは消えます。
私が愚かなことをしているのでしょうか、それともダッシュが誤動作するのでしょうか?私のスクリプトのエラーチェックレベルについて言及しないでください。
今、私たちはこれがUbuntuとDebianの最新バージョンに影響を与える非常に深刻なバグであることを確認しました。誰もが解決策を知っていますか?
答え1
以下は単純化されたテストケースです。
trap '
trap - HUP EXIT || exit "$?"
kill -s HUP "$$" || exit "$?" ' HUP INT
kill -HUP $$
$ dash dash-bug
dash-bug: 3: /home2/ahq/dash-bug: Syntax error: EOF in backquote substitution
参照されたコードの長さや内容を修正すると、バグが「修正」されたり、ランダムバイトが表示されるなど、さまざまな興味深い破損が発生する可能性があります。
これはダッシュ0.5.9以降修正されましたが、Debian 9.8 stable(stretch)、Ubuntu 18.04(bionic)、およびUbuntu 18.10(cosmic)のダッシュ0.5.8にはまだ存在するuse-after-freeバグが原因で発生します。
これは犯罪修正した:
commit 6c3f73bc536082fec38bd36e6c8a121033c68835
Author: Herbert Xu <[email protected]>
Date: Thu Oct 2 08:26:06 2014 +0800
[EVAL] Fix use-after-free in dotrap/evalstring
The function dotrap calls evalstring using the stored trap string.
If evalstring then unsets that exact trap string then we will end
up using freed memory.
This patch fixes it by making evalstring always duplicate the string
before using it.
Signed-off-by: Herbert Xu <[email protected]>
回避策は、トラップハンドラを関数に入れることです。次に、トラップが設定解除された後にコマンドが実行されず、解放された後にジョブ文字列を使用してみます。
sighandler(){
trap - "$sig" EXIT || exit "$?"
kill -s "$sig" "$$" || exit "$?"
}
for sig in HUP INT QUIT ALRM TERM; do
trap "sig=$sig; sighandler" "$sig"
done
kill -s HUP "$$"