向父进程发送信号

向父进程发送信号

我正在尝试为调用大量外部进程的大脚本实现超时。

我启动一个单独的进程作为看门狗,每秒检查是否达到超时

(

  PARENT_PID=$$

  ((t = 2 ))
  while ((t > 0)); do
    sleep 1
    ((t -= 1))
  done

  kill -s ALRM ${PARENT_PID} 2> /dev/null

) &

然后我ALRM在主脚本中捕获信号

trap critical ALRM

最后在关键函数中我打印出一些文本并干净地退出程序

现在问题来了

  • 如果 $PARENT_PID 运行时发生超时,一切都会按预期工作
  • 如果在子进程运行时发生超时(例如,我调用 openssl 并且 openssl 正在运行),则不会发生任何情况。如果我终止正在运行的子进程(例如按CRTL+ C),父进程陷阱将被激活,一切都会按预期继续

我该如何解决这个问题?这样父进程中的陷阱就会被调用并且我可以终止整个进程吗?

更新

如果看门狗杀死-KILL父进程,则处理所有子进程的进程将按预期终止

问题是我想拦截超时并生成一些输出。为此,我使用 ALRM 信号。

信号KILL不能被忽略,而信号可以被忽略ALRM

我目前的想法如下:

  • 父进程有一个警报陷阱
  • 子进程忽略警报信号
  • 当信号发送到父进程时,子进程正在运行,父进程在后台
  • 当孩子终止时我的进程被唤醒

如果这是正确的,我的想法将永远不会奏效。

为了使它工作,我应该为每个子进程

  • 在后台启动它
  • 等待并继续

这样父进程就能捕获信号

我对么?

更新2

一个简化的例子

critical() {
    printf "whathever\n"
    WATCHDOG_PID=$!
    kill -TERM $WATCHDOG_PID
}

(

    PARENT_PID=$$

    ((t = "${TIMEOUT}" ))
    while ((t > 0)); do
        sleep 1
        ((t -= 1))
    done

    kill -s ALRM ${PARENT_PID} 2> /dev/null

) &

trap critical ALRM

# an example of a long running command
(echo 'Q' | openssl s_client -connect corti.li:imap -servername corti.li -verify 6 ) &
wait

WATCHDOG_PID=$!
kill -TERM $WATCHDOG_PID

openssl如果在运行时发送 ALRM 信号,则不会发生任何情况。即使openssl在后台,陷阱也永远不会被调用

答案1

完整的答案需要您父母的代码,但如果缺乏,这里是可能发生的情况的提示:

开放组基本规范第 6 期 -第2.11节

当 shell 等待实用程序执行前台命令完成时接收到已设置陷阱的信号时,与该信号关联的陷阱只有在前台命令完成后才会执行。

当 shell 通过wait实用程序等待异步命令完成时,接收到已设置陷阱的信号应导致实用wait程序立即返回,退出状态 >128,之后立即关联陷阱应采取该信号。

(格式化我的)

这意味着,如果您的父进程正在等待wait命令以外的任何内容,则信号处理会被延迟,直到它正在执行的操作结束为止。

您可以让您的父母等待wait,以便它可以立即收到您的 SIGALRM。

相关内容