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

pcntl_ wait未被SIGTERM中断

莘康裕
2023-03-14

根据pcntl_wait的PHP文档,

wait函数暂停当前进程的执行,直到一个子进程退出,或者直到一个信号被发送,该信号的动作是终止当前进程或者调用一个信号处理函数。

但是,当我运行以下代码并使用kill -s SIGTERM [pid]将SIGTERM发送到父进程时,信号处理程序仅在子进程退出后调用(即我必须等待Hibernate完成。pcntl_wait()不应该被SIGTERM打断吗?

叉子_测试. php:

<?php
  declare(ticks = 1);

  function sig_handler($signo) {
    switch ($signo) {
      case SIGTERM:
        echo 'SIGTERM' . PHP_EOL;
        break;
      default:
    }
  }

  pcntl_signal(SIGTERM, 'sig_handler');

  $pid = pcntl_fork();

  if ($pid == -1) {
     die('could not fork');
  }
  else if ($pid) {
    echo 'parent' . PHP_EOL;

    pcntl_wait($status);
  }
  else {
    echo 'child' . PHP_EOL;
    sleep(30);
  }
?>

输出(SIGTERM 仅在等待 30 秒后出现):

$ php fork_test.php
child
parent
SIGTERM

PHP版本=

共有2个答案

谭翰海
2023-03-14

pcntl_wait调用不能被信号中断,除非restart_syscalls=false或孩子死亡。

waitsyscall的文档中(这就是pcntl_waitcalls):

...它们会阻塞,直到子级更改状态或信号处理程序中断调用(假设系统调用不会使用 sigaction(2)的 SA_RESTART 标志自动重新启动)。

最后一部分非常重要。只有当系统调用没有自动重启时,调用才会被中断(< code > restart _ sys calls = false )。

有趣的是,当进程接收到信号时,并非所有系统调用的行为都是相同的。例如,睡眠系统调用要么等待秒数,要么等待任何信号才能继续。即使您通过restart_syscalls=true睡眠也不会在中断的地方重新启动。来自睡眠手册:

chat()导致调用线程睡眠,直到以秒为单位指定的实时秒数已经过去,或者直到没有忽略的信号到达。

太长别读;pcntl_wait不能被中断,除非你通过restart_syscalls=false

卫弘义
2023-03-14

您对pcntl_signal的调用指定应重新启动调用。检查文档,默认情况下,restart_syscallstrue。因此,您对<code>pcntl_signal</code>的调用在子级终止之前不会返回。

你没必要冲水。因此PHP可以将echo的输出保存在缓冲区中。

因此,您看到的行为正是您请求的行为。重新启动系统调用并缓冲输出。

 类似资料:
  • 问题内容: 在被杀死一次之后,Selenium服务器就挂在所有其他启动上,甚至没有尝试获取服务器端口。 重新启动可解决此问题。以不同的用户身份运行也会使selenium再次启动,但是在 该 进程终止后 , 它将不再起作用。 这是在VirtualBox VM中的Linux 2.6.32-5-amd64(debian压缩)上。查看系统调用的日志,无论何时工作,什么时候不工作,某些组件似乎在套接字绑定之

  • 我在跟踪stackoverflow的帖子 我应该以什么顺序向正常关闭进程发送信号? 并遇到了以下声明。请帮助我理解我以粗体标记的部分。[在答案中找到3票] 守护进程有时使用SIGHUP重新启动或重新加载配置的原因是守护进程从任何控制终端分离,因此永远不会接收SIGTERM,因此该信号被视为“释放”供一般使用。

  • 问题内容: Java中有没有办法处理收到的SIGTERM? 问题答案: 是的,您可以向注册一个关闭挂钩。

  • 问题内容: 我试图绘制一个简单的矩形,但我认为paintComponent方法没有被调用。这是带有main方法的类的代码: 和带有paintComponent()的类 这是什么问题,我不知道… 问题答案: 虽然已经提供的答案可能会导致出现矩形,但这种方法并非最佳。此示例旨在显示一种更好的方法。阅读代码中的注释以获取详细信息。 请注意,应该在EDT上启动Swing / AWT GUI。这留给读者练习

  • 问题内容: 我有一个非常简单的Servlet和一个非常简单的HttpSessionListener: 我的方法从未被调用(没有日志输出),最终我在调用getSession()的那一行上得到一个 我尝试拨打电话时也没有问题,但存在相同的问题。 我不明白- 注释不足以调用我的侦听器吗?Eclipse甚至在下方将其显示为侦听器。 问题答案: 原来这是愚蠢的Eclipse问题之一… Project-> C

  • 我正在尝试使用MethodChannel和Kotlin作为我的语言选择,将Android的Zendesk原生SDK移植到Flatter中。 当我在项目中直接使用Kotlin代码时,它就可以工作了 这个指的是活动,我想应用程序已经在里面了,但是当我试图制作独立的插件时,事情有点不同。我需要实现ActivityAware来获取活动(在flatter插件中获取活动引用)。 https://github.