Webサイトにアクセスすると、テキスト文字列を自動的に強調表示するプラグインを作成しています。これは検索結果のハイライトに似ていますが、自動で多くの単語が含まれます。アレルギーのある人が、食べ物のサイトを閲覧するときなど、言葉を際立たせるために使用できます。
しかし、私には問題があります。空の新しいFFウィンドウを閉じようとすると、プロセス全体が何らかの形でブロックされます。プロセスを強制終了すると、すべてのウィンドウが消えますが、Firefoxプロセスは存続します(親PIDは1で、シグナルをリッスンせず、多くのリソースを開いており、CPUを消費しますが、動きません)。
2つの質問:
プロセスがkill -9(ユーザーとしてもrootとしても)をリッスンしないようにすることもできますか?
再起動以外にできることはありますか?
[編集]これは問題のあるプロセスです:
USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND
digulla 16688 4.3 4.2 784476 345464 pts/14 D Mar28 75:02 /opt/firefox-3.0/firefox-bin
と同じ ps -ef | grep firefox
UID PID PPID C STIME TTY TIME CMD
digulla 16688 1 4 Mar28 pts/14 01:15:02 /opt/firefox-3.0/firefox-bin
残っている唯一のプロセスです。ご覧のとおり、ゾンビではなく、実行中です! PIDで殺しても、名前で殺しても、-9を殺すことを聞きません! strace
で接続しようとすると、strace
もハングし、強制終了できません。出力もありません。私の推測では、FFはいくつかのカーネルルーチンでハングしますが、どれですか?
[編集2] sigjuiceによるフィードバックに基づく:
ps axopid,comm,wchan
プロセスがハングするカーネルルーチンを表示できます。私の場合、問題のプラグインはBeagle Indexer(openSUSE 11.1)でした。プラグインを無効にした後、FFは再びすばやく幸せなキツネになりました。
OPのコメントに記載されているように、プロセスステータス(STAT
)のD
は、プロセスが「割り込み不可能なスリープ」状態であることを示します。実際には、これは通常、I/Oを待機しており、そのI/O操作が完了するまで、死ぬことも含めて何もできない/できないことを意味します。
D
状態のプロセスは通常、操作が完了する前にほんの一瞬だけ存在し、R
/S
に戻ります。私の経験では、プロセスがD
で動かなくなった場合、ほとんどの場合、到達不能なNFSまたは他のリモートファイルシステムと通信しようとしている、障害のあるハードドライブにアクセスしようとしている、または何らかの方法でハードウェアを使用している不安定なデバイスドライバーの。このような場合、回復してプロセスを停止させる唯一の方法は、fs/drive/hardwareをバックアップして実行し、I/Oが完了するか、システムを放棄して再起動することです。 NFSの特定の場合、マウントは最終的にタイムアウトし、I/O操作から(失敗コードで)戻ることもありますが、これはマウントオプションに依存し、NFSマウントが永久に待機するように設定されることは非常に一般的です。
これは、Z
のステータスを持つゾンビプロセスとは異なります。
Parent-idが本当に1であることを再確認してください。そうでない場合、これがfirefox
である場合、最初にSudo killall -9 firefox-bin
を試してください。その後、Sudo killall -9 [process-id]
を使用して特定のプロセスIDを個別に強制終了します。
プロセスがkill -9(ユーザーまたはルートとして不要)をリッスンしないことはどうして可能ですか?
プロセスが<defunct>
を行ってから、親が1で zombie になった場合、できません手動で強制終了します。 init
のみが可能です。ゾンビプロセスはすでに死んでいてなくなっています-もはやプロセスではなく、プロセステーブルエントリとそれに関連する終了コードのみであるため、殺される能力を失い、収集を待っています。親を殺す必要があり、明らかな理由でinit
を殺すことはできません。
しかし、より一般的な情報については here を参照してください。再起動すると、当然すべてが終了します。
私は最近 Double Fork の落とし穴に陥り、最終的に私の答えを見つける前にこのページに到達しました。問題が同じでなくても、症状は同じです。
SNMPデーモンの例に基づいて、最小限のテストコードを以下に示します
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
int main(int argc, char* argv[])
{
//We omit the -f option (do not Fork) to reproduce the problem
char * options[]={"/usr/local/sbin/snmpd",/*"-f","*/-d","--master=agentx", "-Dagentx","--agentXSocket=tcp:localhost:1706", "udp:10161", (char*) NULL};
pid_t pid = fork();
if ( 0 > pid ) return -1;
switch(pid)
{
case 0:
{ //Child launches SNMP daemon
execv(options[0],options);
exit(-2);
break;
}
default:
{
sleep(10); //Simulate "long" activity
kill(pid,SIGTERM);//kill what should be child,
//i.e the SNMP daemon I assume
printf("Signal sent to %d\n",pid);
sleep(10); //Simulate "long" operation before closing
waitpid(pid);
printf("SNMP should be now down\n");
getchar();//Blocking (for observation only)
break;
}
}
printf("Bye!\n");
}
最初のフェーズでは、メインプロセス(7699)がSNMPデーモン(7700)を起動しますが、このデーモンは現在Defunct/Zombieであることがわかります。横に、指定したオプションを持つ別のプロセス(7702)が表示されます
[nils@localhost ~]$ ps -ef | tail
root 7439 2 0 23:00 ? 00:00:00 [kworker/1:0]
root 7494 2 0 23:03 ? 00:00:00 [kworker/0:1]
root 7544 2 0 23:08 ? 00:00:00 [kworker/0:2]
root 7605 2 0 23:10 ? 00:00:00 [kworker/1:2]
root 7698 729 0 23:11 ? 00:00:00 sleep 60
nils 7699 2832 0 23:11 pts/0 00:00:00 ./main
nils 7700 7699 0 23:11 pts/0 00:00:00 [snmpd] <defunct>
nils 7702 1 0 23:11 ? 00:00:00 /usr/local/sbin/snmpd -Lo -d --master=agentx -Dagentx --agentXSocket=tcp:localhost:1706 udp:10161
nils 7727 3706 0 23:11 pts/1 00:00:00 ps -ef
nils 7728 3706 0 23:11 pts/1 00:00:00 tail
10秒間シミュレートした後、わかっている唯一のプロセス(7700)を強制終了します。最後にwaitpid()で成功したもの。しかし、プロセス7702はまだここにあります
[nils@localhost ~]$ ps -ef | tail
root 7431 2 0 23:00 ? 00:00:00 [kworker/u256:1]
root 7439 2 0 23:00 ? 00:00:00 [kworker/1:0]
root 7494 2 0 23:03 ? 00:00:00 [kworker/0:1]
root 7544 2 0 23:08 ? 00:00:00 [kworker/0:2]
root 7605 2 0 23:10 ? 00:00:00 [kworker/1:2]
root 7698 729 0 23:11 ? 00:00:00 sleep 60
nils 7699 2832 0 23:11 pts/0 00:00:00 ./main
nils 7702 1 0 23:11 ? 00:00:00 /usr/local/sbin/snmpd -Lo -d --master=agentx -Dagentx --agentXSocket=tcp:localhost:1706 udp:10161
nils 7751 3706 0 23:12 pts/1 00:00:00 ps -ef
nils 7752 3706 0 23:12 pts/1 00:00:00 tail
Getchar()関数に文字を与えた後、メインプロセスは終了しますが、pid 7002のSNMPデーモンはまだここにあります
[nils@localhost ~]$ ps -ef | tail
postfix 7399 1511 0 22:58 ? 00:00:00 pickup -l -t unix -u
root 7431 2 0 23:00 ? 00:00:00 [kworker/u256:1]
root 7439 2 0 23:00 ? 00:00:00 [kworker/1:0]
root 7494 2 0 23:03 ? 00:00:00 [kworker/0:1]
root 7544 2 0 23:08 ? 00:00:00 [kworker/0:2]
root 7605 2 0 23:10 ? 00:00:00 [kworker/1:2]
root 7698 729 0 23:11 ? 00:00:00 sleep 60
nils 7702 1 0 23:11 ? 00:00:00 /usr/local/sbin/snmpd -Lo -d --master=agentx -Dagentx --agentXSocket=tcp:localhost:1706 udp:10161
nils 7765 3706 0 23:12 pts/1 00:00:00 ps -ef
nils 7766 3706 0 23:12 pts/1 00:00:00 tail
結論
double forkメカニズムを無視したという事実により、killアクションは成功しなかったと考えられました。しかし実際には、間違ったプロセスを単に殺しました!!
-fオプション(Do Not(Double)Fork)を追加することで、すべてが期待どおりになります
このプロセスは、強制終了したときに(たとえばinitによって)再起動される可能性がありますか?
これは簡単に確認できます。 kill -9 PID
の後にPIDが同じ場合、プロセスは強制終了されていませんが、変更されている場合、プロセスは再起動されています。
Sudo killall -9 firefox
動作するはずです
編集:[PID]をfirefoxに変更
ps -ef | grep firefox;そして、あなたは3つのプロセスを見ることができ、それらをすべて殺します。
また、pstreeを実行して親を殺すこともできます。これにより、リーフだけでなく、問題のあるプロセスツリー全体を確実に取得できます。