如何解决在某些子进程变成僵尸之前无法终止它们
环境: Debian 克星,PHP 7.4
几天前我写了一个新的任务管理器,我在终止子进程时遇到了问题。我阅读了以下页面以获取信息:
- Terminating zombie child processes forked from socket server
- https://www.php.net/manual/en/function.pcntl-fork.php
- https://www.php.net/manual/en/function.pcntl-wait.php
- https://unix.stackexchange.com/questions/105998/why-process-program-becomes-zombie
还有其他一些,但这些是最重要的。
所以我的问题是,在我的任务管理器中,我有一个信号接收器函数,理论上应该从内存中清除 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 举报,一经查实,本站将立刻删除。