親がinitである<defunct>プロセスを強制終了するにはどうすればよいですか?


27

NASで送信が断続的に停止しています。SIGTERMを送信しても、プロセスリストから消えず、その<defunct>横にラベルが表示されます。SIGKILLを送信しても、それは消えませんinit。親はであるため、親を終了できません。プロセスを削除して送信を再開できる唯一の方法は、再起動することです。

私ができる最善のことはTransmissionを試して修正することです(そして試してみました)が、私はコンパイルの初心者であり、それをいじり始める前に私の急流が終わったことを確認したかったです。


3
誰も明白なことを述べていない...「init」が所有する<defunct>プロセスは不可能であるべきです!これは非常に奇妙な状況です!本気ですか?
ジョエルファン

@JoelFan:何か重要なことを忘れないようにするために、それをただ見上げていました。の子供であるゾンビは、その多くの一般的なタスクの1つとして定期的に子供を待機しているinitため、かなり早くinit消えるべきです... <defunct>ゾンビと同じですか?
-D.ショーリー

1
nevermind ... <defunct>はゾンビとまったく同じです。initその子を待つので、これは理論的には決して起こらないはずです。を送信するSIGCHLDinitどうなりますか?
-D.ショーリー

@JoelFan:そうだね。PPIDの値は1(初期)だったため、プロセスをSIGKILLすることはできませんでした。
アンディE

回答:


35

<defunct>プロセスはすでに終了しているため、プロセス(ゾンビプロセスとも呼ばれます)を強制終了することはできません。システムは、終了ステータスを収集するために親のゾンビプロセスを保持します。親が終了ステータスを収集しない場合、ゾンビプロセスは永遠に残ります。これらのゾンビプロセスを取り除く唯一の方法は、親を殺すことです。親がinitの場合、再起動のみできます。

ゾンビプロセスはリソースをほとんど使用しないため、ゾンビプロセスを長持ちさせるためのパフォーマンスコストは発生しません。ゾンビプロセスを回避することは、通常、プログラムの一部にバグがあることを意味します。通常、Initはすべての子を収集する必要があります。initにゾンビの子が含まれている場合、initにバグがあります(またはバグではありませんが)。

http://en.wikipedia.org/wiki/Zombie_process


9
initゾンビの子供を持つことはできません。ウィキペディアの記事から:プロセスが親を失うと、initはその新しい親になります。Initは、待機システムコールを定期的に実行して、initを親にしたゾンビを刈り取ります。initの責任の 1つは、孤児や親のいないゾンビを刈り取ることです。
-D.ショーリー

14
@ D.Shawley:initバグがあります。initの置換runitには、この問題を引き起こすバグがあります。
-camh

2
initには、おそらくバグが原因で無効な子が存在する可能性がありますが、可能です。私は今一つを見ているからです。
スタッドギーク

このプログラムがあります。これは、ターミナルから実行して無効状態になりました。@ lesmanaで説明したように、ターミナル(親)を閉じると、プログラムは正常に終了しました。
mk ..

6

Transmission Cのソースコードを修正しようとする人は、ゾンビとシグナルハンドラーを避けるための「ダブルフォーク」トリックについて読む必要があります。また、スマートバリアドスポーン関数の一部として使用する方法についても読んでください(Unixでのスポーンを参照)。

excerpt from: 
   "Spawning in Unix", http://lubutu.com/code/spawning-in-unix

Double fork
This trick lets you spawn processes whilst avoiding zombies, without 
installing any signal handler. The first process forks and waits for its 
child; the second process forks and immediately exits and is reaped;
the third process is adopted by init, and executes the desired program. 
All zombies accounted for, since init is always waiting.

if(fork() == 0) {
   if(fork() == 0) {
       execvp(file, argv);
       exit(EXIT_FAILURE);
   }
   exit(EXIT_SUCCESS);
}
wait(NULL);

1
ダブルフォークは、ゾンビをクリーンアップすることになっているPID 1にカーネルを強制的に設定することにより、ゾンビプロセスを防ぎます。その親はすでにプロセス1であるため、Transmissionはすでにそれを行っているように聞こえます
。-ジャンダー

1
ここには複数の問題があります。#1:親だけが呼び出す必要がありますexit(3); 子は_exit(2)代わりに呼び出す必要があります(そうでない場合、他の問題の中で複数のstdioフラッシュを取得します)。#2:失敗しexecvp(3)perror(3)場合、aを使用できます。#3:signal(SIGCHLD, SIG_IGN)この混乱全体の代わりに使用するだけです。
ケビン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.