3

プロセス グループ内でシグナルが伝達される方法に問題があります。これが私の状況と問題の説明です:

シェルスクリプト(suを使用)によって起動されるアプリケーションがあります。このシェル スクリプト自体は、subprocess.Popen を使用して Python アプリケーションによって起動されます。私は 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()

バッシュスクリプト:

#!/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 アプリケーションでシグナルが表示される場合と表示されない場合があります。別のファイルに直接書き込む方法でプットを置き換えようとしたため、ログの問題ではないと思います。

私の問題の根本的な原因とそれを修正する方法を知っていますか?

4

1 に答える 1

2

シグナル ハンドラーの処理が多すぎます。シグナル ハンドラー内から終了すると、バッファーが適切にフラッシュされているかどうか確信が持てません。つまり、プログラムを正常に終了していない可能性があります。プログラムがすでにシグナルハンドラ内にある場合は、新しいシグナルを受信することに注意してください。

Ruby ソースを変更して、「exit」フラグが設定されたらすぐにメイン ループからプログラムを終了し、シグナル ハンドラ自体から終了しないようにしてください。

Ruby アプリケーションは次のようになります。

#!/usr/bin/env ruby

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

until $done do
    sleep 1
end

puts "** graceful exit"

どちらがはるかに安全なはずです。

実際のプログラムでは、Mutex を使用してフラグ変数を保護することを検討してください。

于 2013-05-24T14:05:46.880 に答える