为什么当我的子进程死亡时,KILL 信号处理程序没有执行



我已经将一些脚本从ksh迁移到bash,我在bash中观察到非常奇怪的行为。我能够减少到一个非常短的片段。

echo first test
LC_ALL=C xclock &
Active_pid=$!
sleep 1
kill -9 $Active_pid
sleep 1
echo second test
LC_ALL=C xclock &
Active_pid=$!
sleep 1
trap "echo Signal SIGKILL caught"  9
kill -9 $Active_pid
sleep 1

输出为

first test
./mig_bash.sh: line 15:  4471 Killed                  LC_ALL=C xclock
second test

我的问题是在第一次测试中产生跟踪。我试图查看是否收到了信号。通过反复试验,我写了解决我问题的"第二次测试"。我不明白。这如何在不执行echo Signal SIGKILL的情况下删除第一个测试的痕迹?

我完全迷失了。

我在 bash 文档中找不到任何可以解释观察到的行为的内容,所以我转向源代码。调试导致功能notify_of_job_status()。仅当以下所有条件成立时,才能到达打印有关已终止子进程的消息的行:

  1. 子流程在作业表中注册(即尚未disown -ed)
  2. 外壳未在交互模式下启动
  3. 终止子进程的信号未捕获在父外壳中(请参阅signal_is_trapped (termsig) == 0检查)

示范:

$ cat test.sh 
echo Starting a subprocess
LC_ALL=C sleep 100 &
Active_pid=$!
case "$1" in
    disown)      disown ;;
    trapsigkill) trap "echo Signal SIGKILL caught"  9 ;;
esac
sleep 1
kill -9 $Active_pid
sleep 1
echo End of script
$ # Demonstrate the undesired message
$ bash test.sh 
Starting a subprocess
test.sh: line 14: 15269 Killed                  LC_ALL=C sleep 100
End of script
$ # Suppress the undesired message by disowning the child process
$ bash test.sh disown
Starting a subprocess
End of script
$ # Suppress the undesired message by trapping SIGKILL in the parent shell
$ bash test.sh trapsigkill
Starting a subprocess
End of script
$ # Suppress the undesired message by using an interactive shell
$ bash -i test.sh 
Starting a subprocess
End of script

这如何在不执行echo Signal SIGKILL的情况下删除第一个测试的痕迹?

陷阱不会执行,因为KILL信号是由子进程接收的,而不是由为其设置陷阱的外壳进程接收的。陷阱对诊断的影响在于notify_of_job_status()函数中的(有点争议的)逻辑。

最新更新