it-swarm.com.de

Wie ist es möglich, dass kill -9 für einen Prozess unter Linux keine Auswirkungen hat?

Ich schreibe ein Plugin, um Textzeichenfolgen automatisch zu markieren, wenn Sie eine Website besuchen. Es ist wie das hervorgehobene Suchergebnis, aber automatisch und für viele Wörter; Es könnte für Allergiker verwendet werden, um Wörter wirklich hervorzuheben, zum Beispiel wenn sie eine Lebensmittelseite durchsuchen.

Aber ich habe problem Wenn ich versuche, ein leeres, neues FF-Fenster zu schließen, blockiert es irgendwie den gesamten Vorgang. Wenn ich den Prozess abschalte, verschwinden alle Fenster, aber der Firefox-Prozess bleibt am Leben (die übergeordnete PID ist 1, hört keine Signale, hat viele Ressourcen offen, frisst immer noch die CPU, aber sie rührt sich nicht).

Also zwei Fragen:

  1. Wie ist es überhaupt möglich, dass ein Prozess nicht auf kill -9 hört (weder als Benutzer noch als Root)?

  2. Kann ich nur einen Neustart durchführen?

[EDIT] Dies ist der beleidigende Prozess:

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

Gleiches mit 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

Es ist der einzige verbleibende Prozess. Wie Sie sehen, ist es kein Zombie, es läuft! Es hört nicht auf kill -9, egal ob ich mit PID oder Namen töte! Wenn ich versuche, mich mit strace zu verbinden, hängt auch die strace und kann nicht abgebrochen werden. Es gibt auch keine Ausgabe. Meine Vermutung ist, dass FF in einer Kernelroutine hängt, aber welche?

[EDIT2] Basierend auf Feedback von Sigjuice: 

ps axopid,comm,wchan

kann Ihnen zeigen, in welcher Kernroutine ein Prozess hängt. In meinem Fall war das fehlerhafte Plugin der Beagle Indexer (openSUSE 11.1). Nach dem Deaktivieren des Plugins war FF wieder ein schneller und fröhlicher Fuchs.

64
Aaron Digulla

Wie in den Kommentaren zum OP vermerkt, zeigt ein Prozessstatus (STAT) von D an, dass sich der Prozess in einem Zustand "unterbrechungsfreier Schlaf" befindet. In der Praxis bedeutet dies im Allgemeinen, dass es auf E/A wartet und nichts tun kann/kann - einschließlich des Sterbens -, bis der E/A-Vorgang abgeschlossen ist.

Prozesse in einem D-Status sind normalerweise nur einen Bruchteil einer Sekunde vor Abschluss der Operation dort und kehren zu R/S zurück. Wenn ein Prozess in D stecken bleibt, versucht er häufig, mit einem nicht erreichbaren NFS oder einem anderen Remote-Dateisystem zu kommunizieren, auf eine fehlerhafte Festplatte zuzugreifen oder mithilfe eines flockigen Gerätetreibers Hardware zu verwenden . In solchen Fällen ist die einzige Möglichkeit, den Prozess wiederherzustellen und zuzulassen, dass der Prozess stirbt, entweder die fs/Laufwerke/Hardware wieder betriebsbereit zu machen, damit die E/A abgeschlossen werden kann, oder das System aufgeben und neu starten. Im speziellen Fall von NFS kann der Mount auch mit der Zeit abbrechen und von der E/A-Operation zurückkehren (mit einem Fehlercode). Dies hängt jedoch von den Mount-Optionen ab und es ist üblich, dass NFS-Mounts so eingestellt sind, dass sie für immer warten .

Dies unterscheidet sich von einem Zombie-Prozess, der den Status Z hat.

124
Dave Sherohman

Vergewissern Sie sich noch einmal, dass die übergeordnete ID wirklich 1 ist. Andernfalls, und dies ist firefox, versuchen Sie zuerst Sudo killall -9 firefox-bin. Versuchen Sie danach, die spezifischen Prozess-IDs mit Sudo killall -9 [process-id] einzeln zu löschen.

Wie ist es überhaupt möglich, dass ein Prozess nicht auf kill -9 hört (neiter als Benutzer oder als root)?

Wenn ein Prozess <defunct> gegangen ist und dann zu einem zombie mit einem übergeordneten Element von 1 wird, können Sie ihn nicht manuell beenden. nur init kann. Zombie-Prozesse sind bereits tot und nicht mehr vorhanden. Sie haben die Fähigkeit verloren zu werden, da sie keine Prozesse mehr sind, sondern nur noch ein Prozesstabelleneintrag und der zugehörige Exit-Code, die darauf warten, gesammelt zu werden. Sie müssen den Elternteil töten, und Sie können init aus offensichtlichen Gründen nicht töten.

Siehe hier für allgemeinere Informationen. Ein Neustart bringt natürlich alles um.

8
John Feminella

Ich bin in letzter Zeit in eine Falle von Double Fork geraten und war auf diese Seite gelandet, bevor ich endlich meine Antwort fand. Die Symptome sind identisch, auch wenn das Problem nicht dasselbe ist:

  • WYKINWYT: Was Sie töten, ist nicht das, was Sie gedacht haben

Der minimale Testcode wird unten anhand eines Beispiels für einen SNMP-Daemon gezeigt

#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");
}

Während der ersten Phase startet der Hauptprozess (7699) den SNMP-Dämon (7700), aber wir können sehen, dass dieser jetzt Defunct/Zombie ist. Daneben sehen wir einen anderen Prozess (7702) mit den von uns angegebenen Optionen

[[email protected] ~]$ 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

Nach den simulierten 10 Sekunden werden wir versuchen, den einzigen uns bekannten Prozess (7700) zu beenden. Was uns schließlich mit waitpid () gelingt. Der Prozess 7702 ist jedoch immer noch da

[[email protected] ~]$ 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

Nachdem wir der getchar () - Funktion ein Zeichen gegeben haben, endet unser Hauptprozess, aber der SNMP-Dämon mit der pid 7002 ist immer noch hier

[[email protected] ~]$ 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

Schlussfolgerung

Die Tatsache, dass wir den Mechanismus Doppelgabel ignorierten, ließ uns glauben, dass die Kill-Aktion keinen Erfolg hatte. Aber in der Tat haben wir einfach den falschen Prozess getötet !!

Durch Hinzufügen der Option -f (Do Not (Double) Fork) wird alles wie erwartet ausgeführt

1
NGI

Ist es möglich, dass dieser Prozess gerade zum Zeitpunkt des Abbruchs neu gestartet wird (zum Beispiel von init)?

Sie können dies leicht überprüfen. Wenn die PID nach kill -9 PID dieselbe ist, wurde der Prozess nicht abgebrochen, aber wenn er geändert wurde, wurde der Prozess erneut gestartet.

1
Georg Schölly
Sudo killall -9 firefox

Sollte arbeiten

BEARBEITEN: [PID] wurde in Firefox geändert

0
karim79

ps -ef | grep firefox; und Sie können 3 Prozess sehen, alle töten.

0
ManofPhysics

Du kannst auch einen Pstree machen und den Elternteil töten. Dadurch wird sichergestellt, dass Sie den gesamten fehlerhaften Prozessbaum und nicht nur das Blatt erhalten.

0
Eric Holmberg