python - 进程组中的所有 child 并不总是看到信号

标签 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。

你们知道我的问题的根本原因是什么以及如何解决吗?

最佳答案

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

尝试修改您的 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 来保护您的标志变量。

关于python - 进程组中的所有 child 并不总是看到信号,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16714297/

相关文章:

python - 在 cloudbuild 中从 python 进行日志记录不起作用

python - Django 在表单上保存未完成的进度

ruby - chruby:如何使用系统默认的ruby?

ruby-on-rails - Ruby on Rails 教程 对 Params 哈希的工作原理感到困惑

linux - 使用 find 和 sed 时出错

linux - 从文件中读取值并将它们与另一个值进行比较的 Shell 脚本

python - 在 ", "上连接 3D pandas 数组中的值,使其成为 2D 数组

python - 将 pandas 数据框中的多类训练示例(行)过度采样和欠采样到指定值

javascript - 如何在 NodeJS 应用程序的服务器端评估 Ruby?

bash - 读取文件并使用 bash 程序将每一行拆分为两个变量