我正在编写一个插件,以便在您访问网站时自动突出显示文本字符串。这就像突出显示搜索结果,但自动和许多单词;它可以用于过敏的人,使单词真正脱颖而出,例如,当他们浏览食物网站时。
但我有问题。当我尝试关闭一个空的,新鲜的FF窗口时,它会以某种方式阻止整个过程。当我终止进程时,所有窗口都消失了,但Firefox进程保持活动状态(父PID为1,不监听任何信号,打开大量资源,仍然占用CPU,但不会让步)。
所以有两个问题:
如果一个进程不听kill -9(无论是用户还是root用户)怎么可能?
除了重启之外,我能做些什么吗?
[编辑]这是违规的过程:
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
这是剩下的唯一过程。正如你所看到的,它不是一个僵尸,它正在运行!它不会听杀-9,无论我是用PID还是名字杀了!如果我尝试与strace
建立联系,那么strace
也会挂起并且无法被杀死。也没有输出。我的猜测是FF挂起了一些内核例程但是哪个?
[EDIT2]根据sigjuice的反馈:
ps axopid,comm,wchan
可以显示进程挂起的内核例程。就我而言,有问题的插件是Beagle Indexer(openSUSE 11.1)。禁用该插件后,FF又是一只快速而快乐的狐狸。
答案 0 :(得分:124)
如对OP的评论中所述,STAT
的进程状态(D
)表示进程处于“不间断睡眠”状态。在现实世界中,这通常意味着它在等待I / O并且不会/不会做任何事情 - 包括死亡 - 直到I / O操作完成。
D
状态的进程通常只会在操作完成之前的几分之一秒内返回R
/ S
。根据我的经验,如果进程陷入D
,它通常会尝试与无法访问的NFS或其他远程文件系统进行通信,尝试访问发生故障的硬盘驱动器,或者通过以下方式使用某些硬件一个片状设备驱动程序。在这种情况下,恢复并允许进程死亡的唯一方法是让fs / drive / hardware备份并运行,以便I / O可以完成或放弃并重启系统。在NFS的特定情况下,安装也可能最终超时并从I / O操作返回(带有故障代码),但这取决于安装选项,并且将NFS安装设置为永久等待是很常见的
这与僵尸流程不同,僵尸流程的状态为Z
。
答案 1 :(得分:8)
仔细检查父ID是否为1.如果不是,并且这是firefox
,请先尝试sudo killall -9 firefox-bin
。之后,尝试使用sudo killall -9 [process-id]
单独删除特定进程ID。
如果一个进程不能监听kill -9(用户还是root用户),它怎么可能呢?
如果某个进程已经<defunct>
,然后变为zombie且父级为1,则无法手动将其删除;只有init
才可以。僵尸进程已经死亡并且已经消失 - 它们已经失去了被杀的能力,因为它们不再是进程,只有进程表条目及其相关的退出代码,等待收集。您需要杀死父级,并且由于显而易见的原因,您无法杀死init
。
但请参阅here了解更多一般信息。重启会自然会杀死所有东西。
答案 2 :(得分:1)
是否有可能在你杀死它的过程中重启这个过程(例如通过init)?
您可以轻松查看此内容。如果在kill -9 PID
之后PID相同,则该过程未被终止,但如果已经更改,则该过程已重新启动。
答案 3 :(得分:1)
我最近陷入了Double Fork的陷阱,并在最终找到答案之前登陆了这个页面。即使问题不一样,症状也是一样的:
下面根据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()取得了成功。但是Process 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()函数赋予一个字符之后,我们的主进程终止了,但是带有pid 7002的SNMP守护进程仍然在这里
[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
结论
我们忽略双叉机制这一事实让我们认为kill操作没有成功。但实际上我们只是杀了错误的过程!!
添加 -f 选项(不要(双)叉)全部按预期进行
答案 4 :(得分:0)
sudo killall -9 firefox
应该工作
编辑:[PID]改为firefox
答案 5 :(得分:0)
ps -ef | grep firefox; 你可以看到3个进程,将它们全部杀掉。
答案 6 :(得分:0)
你也可以做一个pstree并杀死父母。这可以确保您获得整个违规流程树,而不仅仅是叶子。