Как это возможно, что kill -9 для процесса в Linux не имеет никакого эффекта? - PullRequest
64 голосов
/ 29 марта 2009

Я пишу плагин для автоматического выделения текстовых строк при посещении веб-сайта. Это как выделенные результаты поиска, но автоматическое и для многих слов; это может быть использовано для людей с аллергией, чтобы сделать слова действительно выделяющимися, например, когда они просматривают продуктовый сайт.

Но у меня проблема. Когда я пытаюсь закрыть пустое, свежее окно FF, оно как-то блокирует весь процесс. Когда я убиваю процесс, все окна исчезают, но процесс Firefox остается живым (родительский PID равен 1, не слушает никаких сигналов, имеет много открытых ресурсов, все еще ест ЦП, но не сдвигается с места).

Итак, два вопроса:

  1. Как процесс может даже не прослушивать kill -9 (ни как пользователь, ни как root)?

  2. Что я могу сделать, кроме перезагрузки?

[РЕДАКТИРОВАТЬ] Это оскорбительный процесс:

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

Это единственный оставшийся процесс. Как видите, это не зомби, а бег! Он не слушает kill -9, независимо от того, убил ли я PID или имя! Если я пытаюсь соединиться с strace, то strace также зависает и не может быть убит. Выхода тоже нет. Я предполагаю, что FF зависает в какой-то подпрограмме ядра, но какой?

[EDIT2] На основе отзывов sigjuice:

ps axopid,comm,wchan

может показать, в какой подпрограмме ядра зависает процесс. В моем случае плагином-нарушителем был Beagle Indexer (openSUSE 11.1). После отключения плагина FF снова стал быстрой и счастливой лисой.

Ответы [ 7 ]

124 голосов
/ 31 марта 2009

Как отмечено в комментариях к OP, состояние процесса (STAT) D указывает, что процесс находится в состоянии «непрерывного сна». В реальных условиях это обычно означает, что он ожидает ввода-вывода и не может / не будет ничего делать - в том числе и умирать - до тех пор, пока эта операция ввода-вывода не завершится.

Процессы в состоянии D обычно будут присутствовать только в течение доли секунды, прежде чем операция завершится, и они вернутся к R / S. По моему опыту, если процесс застревает в D, он чаще всего пытается связаться с недоступной NFS или другой удаленной файловой системой, пытается получить доступ к отказавшему жесткому диску или использует какое-то оборудование с помощью ненадежного драйвер устройства. В таких случаях единственный способ восстановиться и позволить процессу прекратиться, это либо запустить резервное копирование fs / drive / hardware, чтобы можно было завершить ввод-вывод, либо отказаться и перезагрузить систему. В конкретном случае NFS монтирование может также в конечном итоге прерваться и завершиться с операцией ввода-вывода (с кодом ошибки), но это зависит от параметров монтирования, и очень часто для монтирования NFS устанавливается вечное ожидание .

Это отличается от процесса зомби, который будет иметь статус Z.

8 голосов
/ 29 марта 2009

Дважды проверьте, что родительский идентификатор действительно равен 1. Если нет, то это firefox, сначала попробуйте sudo killall -9 firefox-bin. После этого попробуйте уничтожить отдельные идентификаторы процессов с помощью sudo killall -9 [process-id].

Как вообще возможно, чтобы процесс не прослушивал kill -9 (neiter как пользователь или root)?

Если процесс прошел <defunct>, а затем стал зомби с родителем 1, вы не можете убить его вручную; только init может. Зомби-процессы уже мертвы и ушли - они потеряли способность быть уничтоженными, поскольку они больше не процессы, а только запись таблицы процессов и связанный с ней код завершения, ожидающие сбора. Вам нужно убить родителя, и вы не можете убить init по понятным причинам.

Но см. здесь для получения более общей информации. Естественно, перезагрузка убьет все.

1 голос
/ 15 ноября 2017

В последнее время я попал в ловушку Двойная вилка и попал на эту страницу, прежде чем, наконец, нашел свой ответ. Симптомы идентичны, даже если проблема не одинакова:

  • WYKINWYT: То, что вы убиваете, не то, что вы думали

Минимальный тестовый код показан ниже на основе примера для демона 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 () наш основной процесс завершается, но демон SNMP с pid 7002 все еще здесь

[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 (Не (двойная) вилка) все идет как положено

1 голос
/ 29 марта 2009

Возможно ли, что этот процесс перезапускается (например, init) как раз в тот момент, когда вы его убиваете?

Вы можете легко проверить это. Если PID остается таким же после kill -9 PID, то процесс не был убит, но если он изменился, процесс был перезапущен.

0 голосов
/ 29 марта 2009

Вы также можете сделать pstree и убить родителя. Это гарантирует, что вы получите все дерево процессов, вызывающих ошибки, а не только лист.

0 голосов
/ 29 марта 2009

ps -ef | grep firefox; и вы можете увидеть 3 процесса, убить их всех.

0 голосов
/ 29 марта 2009
sudo killall -9 firefox

Должно работать

РЕДАКТИРОВАТЬ: [PID] изменен на Firefox

...