Как возможно, что kill -9 для процесса в Linux не имеет никакого эффекта?
Я пишу плагин, чтобы автоматически выделять текстовые строки при посещении веб-сайта. Это похоже на результаты поиска, но автоматически и для многих слов; он может быть использован для людей с аллергией, чтобы слова действительно выделялись, например, когда они просматривают сайт пищи.
Но у меня проблема. Когда я пытаюсь закрыть пустое свежее окно FF, он каким-то образом блокирует весь процесс. Когда я убиваю процесс, все окна исчезают, но процесс Firefox остается в живых (родительский PID равен 1, не прослушивает никаких сигналов, имеет много ресурсов, открытых, все еще ест процессор, но не сдвинется с места).
Итак, два вопроса:
-
Как вообще возможно, чтобы процесс не прослушивал kill -9 (ни как пользователь, ни как root)?
-
Есть ли что-нибудь, что я могу сделать, но перезагрузка?
[EDIT] Это нарушающий процесс:
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 (openSUSE 11.1). После отключения плагина FF снова стала быстрой и счастливой лисицей.
Ответы
Ответ 1
Как отмечено в комментариях к OP, статус процесса (STAT
) D
указывает, что процесс находится в состоянии "без прерывания сна". В реальных условиях это обычно означает, что он ожидает ввода-вывода и не может/не будет делать ничего, включая умирание, до тех пор, пока эта операция ввода-вывода не завершится.
Процессы в состоянии D
обычно будут присутствовать только на долю секунды до завершения операции, и они возвращаются к R
/S
. По моему опыту, если процесс застрял в D
, он чаще всего пытается общаться с недоступной NFS или другой удаленной файловой системой, пытаясь получить доступ к отказоустойчивому жесткому диску или использовать какой-то элемент аппаратного обеспечения в виде flaky драйвер устройства. В таких случаях единственный способ восстановить и позволить процессу умереть - либо вернуть резервную копию fs/drive/hardware, чтобы выполнить ввод-вывод, либо отказаться и перезагрузить систему. В конкретном случае NFS mount может также в конечном итоге отключиться и вернуться из операции ввода-вывода (с кодом отказа), но это зависит от параметров монтирования, и очень часто для монтирования NFS должны быть установлены ожидания навсегда.
Это отличается от процесса зомби, который будет иметь статус Z
.
Ответ 2
Дважды проверьте, что parent-id действительно 1. Если нет, и это firefox
, сначала попробуйте sudo killall -9 firefox-bin
. После этого попробуйте уничтожить конкретные идентификаторы процесса отдельно с помощью sudo killall -9 [process-id]
.
Как вообще возможно, чтобы процесс не прослушивал kill -9 (neiter как пользователь или root)?
Если процесс прошел <defunct>
, а затем становится зомби с родителем 1, вы можете 'убить его вручную; только init
жестяная банка. Процессы зомби уже мертвы и исчезли - они потеряли способность убивать, поскольку они больше не обрабатываются, а только запись таблицы процессов и связанный с ней код выхода, ожидающие сбора. Вам нужно убить родителя, и вы не можете убить init
по понятным причинам.
Но см. здесь для получения более общей информации. Перезагрузка, естественно, уничтожит все.
Ответ 3
Возможно ли, что этот процесс будет перезапущен (например, init) только в момент его убийства?
Вы можете легко это проверить. Если после kill -9 PID
PID совпадает с тем, то процесс не был убит, но если он изменился, процесс был перезапущен.
Ответ 4
В последнее время я попал в ловушку в ловушке 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(). Но Process 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 (Do not (Double) Fork), все идет как ожидается
Ответ 5
sudo killall -9 firefox
Должен работать
EDIT: [PID] изменен на firefox
Ответ 6
ps -ef | grep firefox;
и вы можете видеть 3 процесса, убить их всех.
Ответ 7
Вы также можете сделать pstree и убить родителя. Это гарантирует, что вы получите все дерево обработки, а не только лист.