微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在某些子进程变成僵尸之前无法终止它们

如何解决在某些子进程变成僵尸之前无法终止它们

环境: Debian 克星,PHP 7.4

几天前我写了一个新的任务管理器,我在终止子进程时遇到了问题。我阅读了以下页面获取信息:

还有其他一些,但这些是最重要的。

所以我的问题是,在我的任务管理器中,我有一个信号接收器函数,理论上应该从内存中清除 PID,但它并不总是发生。如果它没有发生,就像父进程开始忽略这些信号一样,从那时起就不再重要了,每个子进程都将成为僵尸进程。

所以简化的主流程如下所示:

    public function childCaretaker(int $signo): void
    {
        $this->info("Received PCNTL signal {$signo}");
        $pid = pcntl_wait($status);
        // actually this part below doesn't matter
        if ($pid !== 0 && posix_kill($pid,9)) {
            $this->info("Child {$pid} has tragically died!");
            unset($this->processes[$pid]);
        }
    }
    public function actionRunWorker(bool $priorityLevel = false)
    {
        set_time_limit(0);
        pcntl_async_signals(true);

        pcntl_signal(SIGCHLD,[$this,'childCaretaker']);

        // not important code here
        while (1) {
            // Processes tasks in individual processes if there is any available in the database
            $taskCount = $this->queue->processtasks($this->processes,$priorityLevel);

            // not important code here
        }
    }

然后在实际处理块中,我检查是否有足够的内存从最大可用空间减去安全区来创建新进程。如果有,那么我查询最多 100 个任务,然后使用 foreach 创建新进程 - 如果有足够的内存 - 并为其创建新的数据库连接并在退出关闭它。

    public function processtasks(array &$processes,$priorityLevel = false): int
    {
        // not important code

        /** @var BaseTask $task */
        foreach ($executableTasks as $task) {
            // not important code

            $pid = pcntl_fork();
            // not important code

            switch ($pid) {
                case -1:
                    Yii::error('Could not fork!','tasks');
                    exit(0);
                case 0:
                    // not important code

                    try {
                        // Process the task
                        $task = $this->process($priorityLevel);
                    } catch (\Exception $exception) {
                        // not important code
                        exit(0);
                    }
                    $executionTime = microtime(true) - $taskExecutionStarted;

                    // not important code

                    exit(0);
                default:
                    $processes[$pid] = true;
                    break;
            }
        }

        // not important code
    }

那么我该怎么做才能摆脱僵尸一代呢?在上面的一个链接中,有人解释说它不可能杀死僵尸进程 - 因为它的设计,我在 cli 中手动尝试过,这也有点令人困惑,因为在其他一些来源中,人们提到 SIGKILL 应该总是工作(这不是真的)。​​

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?