我正在编写一个插件,以便在您访问网站时自动突出显示文本字符串。这就像突出显示搜索结果,但自动和许多单词;它可以用于过敏的人,使单词真正脱颖而出,例如,当他们浏览食物网站时。
但我有问题。当我尝试关闭一个空的,新鲜的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又是一只快速而快乐的狐狸。
我知道这不是直接编程相关的,但我对Linux和Unix有很好的了解,我真的很想知道一个进程如何a)吃CPU和b)忽略kill -9? Isnt kill-9应该在这个过程之外完成它的工作吗?
我认为"没有编程相关"是苛刻的。如果Aaron自己修改了firefox代码,并且问了关于linux的确切问题,那么它将与编程相关。操作系统内核行为肯定与编程有关吗?
@Aaron STAT列显示"D",表示"不间断睡眠"。在这种状态下的进程根本不能被杀死。您的主目录是NFS挂载还是Firefox以其他方式访问NFS目录?
@Aaron"ps axopid,comm,wchan"可能会告诉你Firefox内部的例程。
哇!编程相关的问题比这个少得多!
@sigjuice:谢谢,这可能就是我想要的。我回家后会立即尝试。 :)
好吧,我改写了我的问题,因此更多的编程相关。如果您有异议请告诉我。
这是编程相关的,因为它可能非常适合shell脚本,例如在构建系统或自动化测试框架中。
@sigjuice:好的,问题再次开放。请发布你的ps命令,这样我就可以给你当之无愧的+1!
U&L上的这个副本。他们可以合并吗?
这个问题似乎是偏离主题的,因为它是关于Unix和Linux的(unix.stackexchange.com)
如对OP的评论中所述,D的过程状态(STAT)表示该过程处于"不间断睡眠"状态。在现实世界中,这通常意味着它在等待I / O并且不会/不会做任何事情 - 包括死亡 - 直到I / O操作完成。
处于D状态的进程通常仅在操作完成之前的几分之一秒内返回R / S。根据我的经验,如果一个进程卡在D中,它通常会尝试与无法访问的NFS或其他远程文件系统进行通信,尝试访问失败的硬盘驱动器,或者通过片状方式使用某些硬件设备驱动。在这种情况下,恢复并允许进程死亡的唯一方法是让fs / drive / hardware备份并运行,以便I / O可以完成或放弃并重启系统。在NFS的特定情况下,安装也可能最终超时并从I / O操作返回(带有故障代码),但这取决于安装选项,并且将NFS安装设置为永久等待是很常见的。
这与僵尸进程不同,僵尸进程的状态为Z。
是的,可怕的磁盘睡眠:) +1,这是一个很清晰的答案。
呵呵。我不认为这是一种在NFS / SMB /等上设置超时的方法。你进入他的情况之后坐下来?
由于内核错误,您可能还会看到D中存在的问题。
看看最新情况的一个好方法是运行ps -o pid,wchan 1234(插入相关的pid),这将告诉你它在内核中停留的等待通道。您可以在错误报告或谷歌中使用它,它可能会给你一个线索 - 它是否卡在NFS,其他一些驱动程序等等。
好答案!!!一个僵尸进程也不能被杀死(事实上,它是一个僵尸)你必须杀死父亲,所以僵尸得到一个新的父(init)谁总是在做等待(2)它最终死在父母等待(2) )。
仔细检查parent-id是否为1.如果不是,并且这是firefox,请先尝试sudo killall -9 firefox-bin。之后,尝试使用sudo killall -9 [process-id]单独终止特定进程ID。
How is it even possible for a process not to listen to kill -9 (neiter as user nor as root)?
如果一个进程已经然后变为一个父亲为1的僵尸,你就不能手动杀死它;只有init才可以。僵尸进程已经死亡并且已经消失 - 它们已经失去了被杀的能力,因为它们不再是进程,只有进程表条目及其相关的退出代码,等待收集。您需要杀死父级,并且由于显而易见的原因您无法杀死init。
但请参阅此处获取更多一般信息。重启会自然会杀死一切。
它不是僵尸:(
实际上,僵尸不是一个进程,而是一个进程表条目,其唯一目的是将SIGCHLD发送给父进程。 Init自动加入,所以你真的不能拥有PPID == 1的僵尸。
而且我的理解是kill -9会从进程表中删除进程而不会提出很多问题。但似乎一个过程可以以某种方式阻止这种情况。怎么样?
@vartec:你是对的,我的确没有说得那么好。如果你想编辑它,请继续。 @Aaron:死的过程不要听杀信号(没有什么可以杀死的,它们仍然需要收获,所以它们不能消失)。
编辑澄清僵尸不再是一个实际的过程。
我最近陷入了Double Fork的陷阱,并在最终找到答案之前登陆了这个页面。即使问题不一样,症状也是一样的:
WYKINWYT:你所杀的不是你的想法
基于SNMP守护程序的示例,下面显示了最小测试代码
#include
#include
#include
#include
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
",pid);
sleep(10); //Simulate"long" operation before closing
waitpid(pid);
printf("SNMP should be now down
");
getchar();//Blocking (for observation only)
break;
}
}
printf("Bye!
");
}
在第一阶段,主进程(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]
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
结论
我们忽略了双叉机制这一事实使我们认为杀戮行为没有成功。但事实上我们只是杀了错误的过程!!
通过添加-f选项(Do Not(Double)Fork)全部按预期方式运行
是否有可能在您杀死它的过程中重新启动此过程(例如通过init)?
你可以轻松地检查这一点。如果在kill -9 PID之后PID相同,则该过程不会被终止,但如果它已经更改,则该过程已重新启动。
+1的想法,但在我的情况下没有帮助
你也可以做一个pstree并杀死父母。这可以确保您获得整个违规流程树,而不仅仅是叶子。
父母是PID 1时不是一个好主意......
ps -ef | grep firefox;
你可以看到3个进程,全部杀死他们。
我做到了。我杀了,杀了-9,killall。不起作用。
sudo killall -9 firefox
应该管用
编辑:[PID]更改为Firefox
应该但不是。
如果问题与多个实例有关,那么应该将它们全部关闭,而kill -9 PID只会杀死指定的实例。
有趣。当我写评论时,答案是错误的。现在答案是正确的,我的评论已经过时了。但是,答案中没有编辑历史记录。
如果它让你开心,Jorg,我会做一个编辑。我们度过了糟糕的一天,是吗?
这更像是对网站行为的观察。帖子可以编辑的事实是SO的工作原理。但是,我不知道可以编辑帖子而不会将它们显示为已编辑,这有点奇怪。
我认为编辑X分钟之前的事情会在一分钟左右后出现,这就是编辑后的答案最初标记为编辑的原因。我也注意到了。