当前位置: 首页 > 知识库问答 >
问题:

PHP防止SIGTERM冒泡proc_open进程

陶俊晤
2023-03-14

原始问题(在CTRL C上向孩子发送SIGTERM,父母应该等待它关闭)。请参阅下面的更新!

我有一个PHP脚本(见下文)启动一个进程并跟踪它的输出。这个过程一直运行,直到我通过按CTRL+C或者向PHP脚本(pid)发送一个SIGTERM信号来请求PHP停止。此时,PHP决定立即终止由proc_open启动的进程,而不是优雅地关闭它,并在关闭自己之前等待它,我该如何实现这一点?

我尝试了一些东西,如添加< code > pcntl _ waitpid($ child PID)等,但到目前为止,显然没有运气。

<?php

// Handle close signals (like CTRL+C).
function closeChildApplication(int $signal) {
    // ???
}

// Async signals instead of declare(TICKS=1) PHP 7.1+
pcntl_async_signals(true);
pcntl_signal(SIGTERM, 'closeChildApplication', false);
pcntl_signal(SIGINT, 'closeChildApplication', false);

// Create process.
$descriptors = [
    0 => ['pipe', 'r'],
    1 => ['pipe', 'w'],
    2 => ['pipe', 'w']
];
$proc = proc_open('<command-to-run>', $descriptors, $pipes);
if (!is_resource($proc)) {
    throw new \RuntimeException('Could not execute <command-to-run>.');
}

// Not sending any data to child, so close STDIN immediately.
fclose($pipes[0]);

// Non blocking mode.
stream_set_blocking($pipes[1], false);
stream_set_blocking($pipes[2], false);

do {
    $status = proc_get_status($proc);

    $data = '';
    while (!feof($pipes[1]) && false !== ($line = fgets($pipes[1]))) {
        $data .= $line;
    }
    if (!empty(trim($data))) {
        // STDOUT logic here.
    }

    $data = '';
    while (!feof($pipes[2]) && false !== ($line = fgets($pipes[2]))) {
        $data .= $line;
    }
    if (!empty(trim($data))) {
        // STDERR logic here.
    }

    sleep(1);
} while ($status['running']);

// Not running anymore, close resource.
fclose($pipes[1]);
fclose($pipes[2]);
proc_close($proc);

更新:PHP似乎在等待关闭child,但所讨论的程序没有很好地处理SIGTERM和SIGINT,并立即杀死自己,而不是清理和关闭。我发现我可以向程序STDIN发送QUIT命令以触发完全关闭。

但我现在面临的问题是,当PHP接收到SIGTERM/SIGINT信号时,它也会被发送到用proc_open打开的程序(因此它会向下冒泡到子进程)。

如果发现了,我们可以玩一玩<code>pcntl_signal(SIGTERM,SIG_IGN,false),这会导致PHP忽略该信号并阻止将其发送给子级。但现在我不知道是否发出了信号。

另一种方法是这样做:

function closeChildApplication(int $signal) {
    // do nothing in here.
}

pcntl_signal(SIGTERM, 'closeChildApplication', false);

在这种情况下,PHP忽略信号并保持运行,但孩子收到它并被杀死。任何知道如何防止信号冒泡给孩子或忽略信号的人,但例如在下面检查是否收到任何信号?

共有1个答案

董子平
2023-03-14

因此,经过几天对这个问题的困惑,如果发现proc_open似乎有点继承了PHP关于SIG_IGN信号的设置。

当说<code>pcntl_信号时(SIGTERM,SIG_IGN,false)PHP和proc_open打开的进程都忽略了这个信号。

当说pcntl_signal(SIGTERM, function(){echo'test';}, false);时,PHP会回显'test'并继续运行,但是proc_open打开的进程也在接收SIGTERM并自行关闭。

但有趣的是,当我这么做的时候:

// Ignore all signals:
pcntl_signal(SIGTERM, SIG_IGN, false);

// Start program:
proc_open('command // etc');

// Install signal handler for PHP:
pcntl_signal(SIGTERM, function(){ echo 'test'; }, false);

PHP在接收信号时回显“test ”,但是以proc_open开始的进程没有对SIGTERM信号做任何事情,这向我表明SIG_IGN是由proc_open继承的。

这正是我现在需要的,但有点奇怪的是,这是告诉proc_open忽略一些信号的唯一方式,不确定这是有意的行为还是PHP的错误。

 类似资料:
  • 本文向大家介绍jQuery如何防止这种冒泡事件发生,包括了jQuery如何防止这种冒泡事件发生的使用技巧和注意事项,需要的朋友参考一下 冒泡事件就是点击子节点,事件会向上传递,最后触发父节点,祖先节点的点击事件。 html代码部分: jQuery代码如下: 当点击span时,会触发div与body 的点击事件。点击div时会触发body的点击事件。 如何防止这种冒泡事件发生呢?修改如下:     

  • 我有一个单线程进程,它不会在终止条件下死亡。处理信号掩码未显示SIGTERM被阻塞。我以root身份执行“kill”。我可以使用SIGKILL终止进程,但这是更大系统的一部分,我希望SIGTERM能够工作。 注意Sig*属性。SigCgt、SigIgn和SigBlk表示SIGTERM既没有被捕获、忽略或阻塞(第15位未设置-将最低有效位计算为#1)。由于SIGTERM的默认配置是终止进程,我希望它

  • 本文向大家介绍利用JQuery阻止事件冒泡,包括了利用JQuery阻止事件冒泡的使用技巧和注意事项,需要的朋友参考一下 冒泡事件就是点击子节点,会向上触发父节点,祖先节点的点击事件。 我们在平时的开发过程中,肯定会遇到在一个div(这个div可以是元素)包裹一个div的情况,但是呢,在这两个div上都添加了事件,如果点击里面的div我们希望处理这个div的事件,但是呢,我们不希望外层的div的事件

  • 提示冒泡受启发自Jason Frame开发的极好的jQuery Tipsp插件,它是一个改进版本,不依赖于图片,使用CSS3实现动画,利用data-attribute实现本地化标题存储。 概述 在使用提示冒泡插件的时候你需要知道这些: 提示冒泡依赖第三方库Tether实现定位。你必须在bootstrap.js之前调用 tether.min.js,才能使提示冒泡起作用。 出于性能的原因,提示冒泡是选

  • 注意 目前仅 Weex Native(Android 和 iOS)支持,web 端 暂时不支持此项特性. 如果你是个 web 开发者,你大概对浏览器事件冒泡机制已经很熟悉了,而且可能认为 Weex 默认会支持事件冒泡。然而,Weex 在 0.13 之前是不支持这一特性的,在 0.13 版本,Weex 提供了这项支持。 概念 以点击事件为例,比如一个点击事件发生在某个 <video> 元素上,这个元

  • 冒泡排序(Bubble Sort)也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 作为最简单的排序算法之一,冒泡排序给我的感觉就像 Abandon 在单词书里出现的感觉一样,每次都在第一页第一位