当对话框使用自定义 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 时,脚本将退出而不打印任何内容。如果我删除其中一个,set -x否则BASH_XTRACEFD="5"它将正常工作并捕获陷阱并执行 _reboot 函数。但是如果我将两者都保留(我需要出于调试目的) - 那么 trap 就失去了所有意义。

退出代码是 141,当我使用 CTRL+C 退出时,这很有趣。如果我让脚本运行,它很自然地会以 0 退出,但是如果我删除set -x或中的任何一个,BASH_XTRACEFD="5"然后CTRL+C我将以 55 退出。

由于某种原因,这种情况仅在屏幕上出现对话框时发生。例如,如果我这样做

while true; do
  sleep 5
done

然后exit with CTRL+Ctrap就会被执行。

我需要帮助来解决这个问题。

编辑:可能值得一提的是 bash 版本是 5.1.16,在 Alpine 3.16 上运行

答案1

对话框使用 ncurses,它捕获SIGINT,如initscr联机帮助页部分中所述信号处理器

SIGINT
处理程序尝试在退出时清理屏幕。虽然它通常按预期工作,但也有局限性:

  • 遍历 SCREEN 列表是不安全的,因为所有列表管理都是在没有任何信号阻塞的情况下完成的。
  • 在打开 REENTRANT 的系统上,set_term 使用的函数可能会死锁或以其他方式出现错误。
  • endwin 调用其他函数,其中许多函数使用 stdio 或其他库函数,这显然是不安全的。

只有当子进程没有首先捕获信号时,bash 才会“看到”该信号。

相关内容