65

我正在编写一个插件来在您访问网站时自动突出显示文本字符串。就像高亮搜索结果一样,但是是自动的,并且适用于许多单词;它可以用于过敏症患者,让文字真正脱颖而出,例如,当他们浏览美食网站时。

但我有问题。当我尝试关闭一个空的、新鲜的 FF 窗口时,它会以某种方式阻止整个过程。当我终止进程时,所有窗口都消失了,但 Firefox 进程仍然存在(父 PID 为 1,不听任何信号,有很多资源打开,仍然占用 CPU,但不会让步)。

所以两个问题:

  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 又是一只又快又快乐的狐狸了。

4

7 回答 7

125

正如对 OP 的评论中所指出的,进程状态 ( STAT)D表示进程处于“不间断睡眠”状态。在现实世界中,这通常意味着它正在等待 I/O 并且不能/不会做任何事情 - 包括死亡 - 直到 I/O 操作完成。

处于某个状态的进程D通常只会在操作完成之前存在几分之一秒,然后它们会返回R/ S。根据我的经验,如果一个进程卡在D,它最常尝试与无法访问的 NFS 或其他远程文件系统进行通信,尝试访问发生故障的硬盘驱动器,或通过不稳定的设备驱动程序使用某些硬件。在这种情况下,恢复并允许进程终止的唯一方法是让 fs/驱动器/硬件备份并运行,以便 I/O 可以完成,或者放弃并重新启动系统。在 NFS 的特定情况下,挂载也可能最终超时并从 I/O 操作返回(带有失败代码),但这取决于挂载选项,并且 NFS 挂载设置为永远等待是很常见的.

这与僵尸进程不同,僵尸进程的状态为Z.

于 2009-03-31T14:07:48.057 回答
8

仔细检查 parent-id 是否真的是 1。如果不是,这是firefox,首先尝试sudo killall -9 firefox-bin。之后,尝试使用 . 单独杀死特定的进程 ID sudo killall -9 [process-id]

一个进程怎么可能不听kill -9(既不是用户也不是root)?

如果一个进程已经走了<defunct>,然后变成了一个父级为 1 的僵尸,你不能手动杀死它;只能init。僵尸进程已经死亡并消失了——它们已经失去了被杀死的能力,因为它们不再是进程,只有一个进程表条目及其相关的退出代码,等待收集。你需要杀死父母,你不能init因为明显的原因而杀死。

但请参阅此处了解更多一般信息。重启自然会杀死一切。

于 2009-03-29T14:44:37.577 回答
1

是否有可能在您杀死它时重新启动该进程(例如通过init)?

您可以轻松地检查这一点。如果之后 PID 相同,kill -9 PID则不会终止该进程,但如果它已更改,则该进程已重新启动。

于 2009-03-29T15:12:27.497 回答
1

我最近陷入了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)

[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() 函数一个字符后,我们的主进程终止,但 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选项( Do Not (Double) Fork )一切都按预期进行

于 2017-11-14T23:15:11.333 回答
0
sudo killall -9 firefox

应该管用

编辑:[PID] 更改为 firefox

于 2009-03-29T14:42:39.877 回答
0

ps -ef | grep 火狐;你可以看到 3 个进程,将它们全部杀死。

于 2009-03-29T14:44:02.323 回答
0

您也可以执行 pstree 并杀死父级。这可以确保您获得整个有问题的进程树,而不仅仅是叶子。

于 2009-03-29T15:09:47.597 回答