システムで奇妙な動作をします。
シェル(bashバージョン4.2.45(1)-リリース)でコマンド、たとえばtop
またはcat
を呼び出すと、実行中のプログラム(プロセス)が応答しません Ctrl+C。 kill -2 <pid>
とkill -15 <pid>
を実行しようとしましたが、役に立ちませんでした。ただし、SIGKILL
を使用してプロセスを強制終了できます。
私はプロセスを所有しており、ルートとしてプロセスに信号(信号2と15)を送信しようとしましたが、応答しませんでした。 top
を押すと、q
を終了できます。
問題について何か考えはありますか?またはそれをトラブルシューティングするためのヒントはありますか?
更新1
cat
とtop
は単なる例です。すべてのプロセスの動作は同じです。スリープのみ(シグナルハンドラーなし)の単純なプログラムを作成しようとしましたが、同じ動作をしました。
更新2
私は寝るだけの小さなプログラムを書きました。今回は、SIGTERM
とSIGINT
をキャッチするシグナルハンドラーをインストールしました。 kill -15 <pid>
を呼び出したとき(および-2
を使用したとき)、プログラムは信号を受信しませんでした。
また、カーネルを3.11.10-100.fc18.i686
に更新しましたが、それでも同じ問題が発生します。
NVidiaプロプライエタリドライバーの最近のバージョン(おそらく他の最近のバージョンのライブラリと組み合わせて)には、シグナルマスクを破損させるバグがあります。
次のようなシグナルマスクを見ることができます。
anthony@Zia:~$ ps -eo blocked,pid,cmd | egrep -v '^0+ '
BLOCKED PID CMD
fffffffe7ffbfeff 605 udevd --daemon
0000000000000002 4052 /usr/lib/policykit-1/polkitd --no-debug
0000000000087007 4646 /usr/sbin/mysqld --basedir=/usr […]
0000000000010000 15508 bash
それはそれがどのように見えるべきかについてです。プロプライエタリなnVidiaドライバーを備えたシステムでこれを実行すると、多くのプログラムでBLOCKED
のあらゆる種類のクレイジーな値が表示されます。これには、おそらくすべての誤動作プログラムも含まれます。
シグナルマスクはfork
/exec
を介して親から子に渡されるため、親プロセスに破損したプロセスがあると、それ以降に生成されるすべての子も同様に渡されることに注意してください。
私の質問アップグレード後、タイトルバーのXボタンがxtermを閉じなくなりましたおよびさまざまなディストリビューションのバグも参照してください。どのパッケージを見るかを知って、今すぐ見つけてください。その質問に対する私の回答のコードを変更して、シグナルマスクをブロックなしにリセットできます(sigaddset
を削除し、SIG_UNBLOCK
をSIG_SETMASK
に変更します)。
これはtop
からの望ましい動作だと思います。キーボードからの「q」コマンドでのみ終了します。
top
のコードは、おそらくsignal()
システムコールまたはsigaction()
システムコールのいずれかでシグナルキャッチャー関数をインストールします。私の推測では、top
が定期的に画面を更新すると、alarm()
システムコールなどから信号を受信した可能性があります。
cat
がcontrol-Cまたはcontrol- \で終了しないことを確認しますか?これらのキーコードは両方とも、通常、それぞれSIGINTとSIGQUITを生成します。 cat
は、これら2つのシグナルのいずれかから回復してもメリットがないようです。
TtyドライバーがSIGINTとSIGQUITのキーコードであると考えていることを確認する1つの方法は次のとおりです。
stty -a
私のマシンでは、次のように表示されます。
speed 38400 baud; rows 24; columns 80; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^D; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z; rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 0;
-parenb -parodd cs8 -hupcl -cstopb cread -clocal -crtscts -cdtrdsr
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr icrnl ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
opost -olcuc -ocrnl onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0 bs0 vt0 ff0
isig icanon iexten echo echoe echok -echonl -noflsh -xcase -tostop -echoprt
echoctl echoke
「intr = ^ C」および「quit = ^ \」は、「SIGINTをControl-Cの現在のフォアグラウンドプロセスに送信する」および「SIGQUITをControl-backslashの現在のフォアグラウンドプロセスに送信する」ことを意味します。それらの2つはどういうわけか変更されましたか?
シェルが信号をトラップするように設定されている場合があります。 zshとbashでは、コマンドは次のとおりです。
trap "" INT
control-C(同じxterm内)が後続のcat
の呼び出しを強制終了しないようにします。しかし、その「トラップ」は、kill -QUIT
がcat
プロセスを終了させるのを防ぎません。それでも、bash、zsh、またはkshドットファイルでtrap "" INT
呼び出しを確認する必要があります。
どのカーネルバージョン、どのディストリビューション、どのシェルを使用しているかについては言及していません。それらのことについて言及すると、より良い答えが得られるかもしれません。