进程组中的所有子项并不总能看到信号

时间:2013-05-23 12:44:35

标签: python ruby bash process signals

我在进程组中传播信号的方式存在问题。这是我的情况和问题的解释:

我有一个应用程序,它由shell脚本(带有su)启动。这个shell脚本本身是由python应用程序使用subprocess.Popen启动的 我将os.setpgrp称为preexec_function,并使用ps验证了bash脚本,su命令和最终应用程序都具有相同的pgid。

现在,当我将信号USR1发送到bash脚本(进程组的负责人)时,有时应用程序会看到此信号,有时则看不到。我无法弄清楚为什么我有这种随机行为(应用程序大约有50%的时间看到该信号)

以下是我正在测试的示例代码:

Python启动器:

#!/usr/bin/env python
p = subprocess.Popen( ["path/to/bash/script"], stdout=…, stderr=…, preexec_fn=os.setpgrp )
# loop to write stdout and stderr of the subprocesses to a file
# not that I use fcntl.fcntl(p.stdXXX.fileno(), fcntl.F_SETFL, os.O_NONBLOCK)
p.wait()

Bash脚本:

#!/bin/bash

set -e
set -u

cd /usr/local/share/gios/exchange-manager

CONF=/etc/exchange-manager.conf
[ -f $CONF ] && . $CONF

su exchange-manager -p -c "ruby /path/to/ruby/app"

Ruby应用程序:

#!/usr/bin/env ruby
Signal.trap("USR1") do
    puts "Received SIGUSR1"
    exit
end

while true do
    sleep 1
end

所以我尝试将信号发送到bash包装器(从终端或python应用程序),有时ruby应用程序将看到信号,有时不会。我不认为这是一个日志记录问题,因为我试图通过直接写入不同文件的方法替换puts。

你们有什么想法可能是我的问题的根本原因以及如何解决它?

1 个答案:

答案 0 :(得分:2)

你的信号处理程序做得太多了。如果从信号处理程序中退出,则不确定缓冲区是否已正确刷新,换句话说,您可能无法正常退出程序。当程序已在信号处理程序中时,请注意接收的新信号。

设置“exit”标志后,尝试修改Ruby源以从主循环中退出程序,并且不要退出信号处理程序本身。

您的Ruby应用程序变为:

#!/usr/bin/env ruby

$done = false
Signal.trap("USR1") do
    $done = true
end

until $done do
    sleep 1
end

puts "** graceful exit"

哪个应该更安全。

对于真实程序,您可以考虑使用Mutex来保护您的标志变量。