web-dev-qa-db-ja.com

プロセスが私のシグナルに応答しない

システムで奇妙な動作をします。

シェル(bashバージョン4.2.45(1)-リリース)でコマンド、たとえばtopまたはcatを呼び出すと、実行中のプログラム(プロセス)が応答しません Ctrl+Ckill -2 <pid>kill -15 <pid>を実行しようとしましたが、役に立ちませんでした。ただし、SIGKILLを使用してプロセスを強制終了できます。

私はプロセスを所有しており、ルートとしてプロセスに信号(信号2と15)を送信しようとしましたが、応答しませんでした。 topを押すと、qを終了できます。

問題について何か考えはありますか?またはそれをトラブルシューティングするためのヒントはありますか?

更新1

cattopは単なる例です。すべてのプロセスの動作は同じです。スリープのみ(シグナルハンドラーなし)の単純なプログラムを作成しようとしましたが、同じ動作をしました。

更新2

私は寝るだけの小さなプログラムを書きました。今回は、SIGTERMSIGINTをキャッチするシグナルハンドラーをインストールしました。 kill -15 <pid>を呼び出したとき(および-2を使用したとき)、プログラムは信号を受信しませんでした。

また、カーネルを3.11.10-100.fc18.i686に更新しましたが、それでも同じ問題が発生します。

5
Maxwell S.

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_UNBLOCKSIG_SETMASKに変更します)。

6
derobert

これは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 -QUITcatプロセスを終了させるのを防ぎません。それでも、bash、zsh、またはkshドットファイルでtrap "" INT呼び出しを確認する必要があります。

どのカーネルバージョン、どのディストリビューション、どのシェルを使用しているかについては言及していません。それらのことについて言及すると、より良い答えが得られるかもしれません。

0
Bruce Ediger