カスタムBASH_XTRACEFDを使用してダイアログボックスを実行すると、トラップは無視されます。

カスタムBASH_XTRACEFDを使用してダイアログボックスを実行すると、トラップは無視されます。

次のスクリプトがあります

#!/bin/bash

exec 5> >(logger -t $0)
BASH_XTRACEFD="5"
set -x

trap _reboot INT

DIALOG_TITLE="This is fancy dialog title"

_reboot() {
        echo Exiting
        exit
}

dialog --title "${DIALOG_TITLE}" --yesno "Welcome to Dialog" 0 0

ただし、CTRL + Cを実行すると、何も印刷されずにスクリプトが終了します。そのうちの1つを削除するとset -x正常にBASH_XTRACEFD="5"動作し、トラップをキャプチャして_reboot関数を実行します。しかし、デバッグ目的で必要な両方を維持すると、トラップはすべての意味を失います。

終了コードは141ですが、CTRL + Cを使用して終了すると面白いです。スクリプトを実行すると自然に 0 で終了しますが、set -xいずれかを削除するBASH_XTRACEFD="5"CTRL+C55 で終了します。

何らかの理由で、この問題はダイアログボックスが画面に表示された場合にのみ発生します。たとえば、私がそうした場合

while true; do
  sleep 5
done

その後、トラップを使用してシャットダウンがCTRL+C実行されます。

この問題を解決するには助けが必要です。

編集:bashバージョンは、Alpine 3.16で動作する5.1.16であることに言及する価値があります。

答え1

ダイアログボックスは、マンページのセクションで説明されているようにをSIGINTキャプチャするためにncursesを使用します。initscr信号プロセッサ:

SIGINT
ハンドラは終了時に画面のクリーンアップを試みます。通常、期待どおりに機能しますが、次の制限があります。

  • SCREENリストをナビゲートすることは、すべてのリスト管理がシグナルブロックなしで実行されるため安全ではありません。
  • REENTRANTがオンのシステムでは、set_termで使用されている関数がデッドロックに陥ったり、エラーが発生したりする可能性があります。
  • endwinはstdioや他のライブラリ関数を使用する他の関数を呼び出しますが、これは確かに安全ではありません。

Bash は、サブプロセスが最初にシグナルを捕捉できない場合にのみシグナルを「認識」します。

関連情報