Wie kann ich einen <defunct> -Prozess beenden, dessen übergeordnetes Element init ist?

27

Die Übertragung hängt zeitweise an meinem NAS. Wenn ich SIGTERM sende, verschwindet es nicht aus der Prozessliste und ein <defunct>Etikett wird daneben angezeigt. Wenn ich ein SIGKILL sende, verschwindet es immer noch nicht und ich kann das übergeordnete Element nicht beenden, da es das übergeordnete Element ist init. Der einzige Weg, den Prozess loszuwerden und Transmission neu zu starten, ist ein Neustart.

Mir ist klar, dass das Beste, was ich tun kann, darin besteht, Transmission zu reparieren (und ich habe es versucht), aber ich bin ein Anfänger beim Kompilieren und wollte sicherstellen, dass meine Torrents fertig sind, bevor ich anfange, damit herumzuspielen.

Andy E
quelle
3
Niemand gibt das Offensichtliche an ... ein <defunct> -Prozess von "init" sollte unmöglich sein! Dies ist eine sehr merkwürdige Situation! Bist du sicher?
JoelFan
@JoelFan: Ich habe nur nachgesehen, um sicherzugehen, dass ich nichts Wichtiges vergessen habe. Zombies, deren Kinder sind, initsollten ziemlich schnell initverschwinden, da sie regelmäßig auf Kinder warten, da dies eine der häufigsten Aufgaben ist. Ist <defunct>das dasselbe wie ein Zombie?
D. Shawley
1
vergiss es ... <defunct>ist genau das gleiche wie ein Zombie. initwird auf seine Kinder warten, so sollte dies theoretisch nie passieren. Ich frage mich , was passiert , wenn Sie ein senden SIGCHLDan init?
D. Shawley
@ JoelFan: Ja, ich bin sicher. Der Wert für PPID war 1 (init), daher war es unmöglich, den Prozess abzubrechen.
Andy E
3
ähnlich wie unix.stackexchange.com/a/5648
tshepang

Antworten:

35

Sie können einen <defunct>Prozess (auch als Zombie-Prozess bezeichnet) nicht beenden, da er bereits tot ist. Das System speichert Zombie-Prozesse, damit die Eltern den Exit-Status abrufen können. Wenn das übergeordnete Element den Beendigungsstatus nicht erfasst, bleiben die Zombieprozesse für immer bestehen. Die einzige Möglichkeit, diese Zombie-Prozesse loszuwerden, besteht darin, die Eltern zu töten. Wenn das übergeordnete Element init ist, können Sie nur einen Neustart durchführen.

Zombie-Prozesse beanspruchen fast keine Ressourcen, so dass es keine Leistungskosten gibt, wenn sie verweilen. Obwohl das Vorhandensein von Zombie-Prozessen in der Regel bedeutet, dass einige Ihrer Programme fehlerhaft sind. Init sollte normalerweise alle Kinder sammeln. Wenn init Zombie-Kinder hat, dann gibt es einen Fehler in init (oder anderswo, aber einen Fehler).

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

Lesmana
quelle
9
initkann nie Zombiekinder haben. Aus dem Wikipedia-Artikel: Wenn ein Prozess sein übergeordnetes Element verliert, wird init zu seinem neuen übergeordneten Element. Init führt regelmäßig den Systemaufruf wait aus, um alle Zombies mit init als übergeordnetem Element zu ernten. Eine seiner initAufgaben ist es, Waisen und elternlose Zombies zu ernten.
D. Shawley
14
@ D.Shawley: initKann aber Bugs haben. Die Init-Ersetzung runithatte einen Fehler, der dieses Problem verursacht.
camh
2
init kann verstorbene Kinder haben, vielleicht aufgrund eines Fehlers, aber es kann. Weil ich mir gerade einen ansehe.
Studgeek
Es gibt dieses Programm, das ich vom Terminal aus ausgeführt und in den Zustand "Nicht mehr funktionsfähig" versetzt habe. Wie von @lesmana erklärt, wurde das Programm beim Schließen des Terminals (übergeordnetes Programm) ordnungsgemäß beendet.
mk ..
6

Jeder, der versucht, den Transmission C-Quellcode zu reparieren, sollte etwas über den "Double Fork" -Trick lesen, um Zombies und Signal-Handler zu vermeiden ... und darüber, wie er als Teil einer intelligenten variadischen Spawn-Funktion verwendet werden kann (siehe Spawning in 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);
Nazar
quelle
1
Die Doppelgabel verhindert Zombie-Prozesse, indem sie den Kernel zwingt, die übergeordnete Komponente auf PID 1 zu setzen, die Zombies bereinigen soll. Es hört sich so an, als ob Transmission es bereits tut, da sein Elternteil bereits Prozess 1 ist.
Jander
1
Hier gibt es mehrere Probleme. # 1: Nur der Elternteil sollte anrufen exit(3); Die Kinder sollten _exit(2)stattdessen anrufen (ansonsten erhalten Sie unter anderem mehrere Stdio-Flushes). # 2: Das execvp(3)könnte ein perror(3)brauchen, wenn es fehlschlägt. # 3: Du solltest einfach signal(SIGCHLD, SIG_IGN)anstatt dieses ganzen Chaos verwenden.
Kevin