it-swarm.com.ru

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

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

Но у меня есть проблема. Когда я пытаюсь закрыть пустое, свежее окно 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 снова стала быстрой и счастливой лисой.

64
Aaron Digulla

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

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

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

124
Dave Sherohman

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

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

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

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

8
John Feminella

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

  • 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) с указанными параметрами

[[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

После 10 секунд симуляции мы попытаемся убить единственный известный нам процесс (7700). Что мы добились в конце концов с waitpid (). Но процесс 7702 все еще здесь

[[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

После передачи символа в функцию getchar () наш основной процесс завершается, но демон SNMP с pid 7002 все еще здесь

[[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

Заключение

Тот факт, что мы игнорировали механизм double fork, заставил нас думать, что действие kill не было успешным. Но на самом деле мы просто убили неправильный процесс !!

При добавлении опции -f (Не (двойная) вилка) все идет как положено

1
NGI

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

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

1
Georg Schölly
Sudo killall -9 firefox

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

Правка: [PID] изменен на Firefox

0
karim79

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

0
ManofPhysics

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

0
Eric Holmberg