为何注册SIGHUP信号处理函数后,XTerm无法关闭等待输入的PHP CLI进程?
解决方案
问题根源
点击XTerm关闭按钮时,终端会给子进程(PHP脚本)发送SIGHUP信号。你注册的空信号处理函数覆盖了默认的终止行为,再加上PHP的pcntl_signal默认启用SA_RESTART标志——这个标志会让被信号中断的阻塞系统调用(比如fgets(STDIN))自动重启,导致脚本继续卡在等待输入状态,XTerm因为子进程未退出,窗口无法关闭。之前添加exit(1)无效,是因为SA_RESTART让脚本回到了fgets,没机会执行退出逻辑。
修复代码
修改后的脚本同时处理信号中断问题,保留你需要的所有逻辑,还能执行关闭前的清理:
<?php // 启用异步信号处理,确保信号触发时立即执行处理函数 pcntl_async_signals(true); $exitTriggered = false; function cleanup_and_exit() { global $exitTriggered; if ($exitTriggered) return; // 避免重复执行清理 $exitTriggered = true; // 这里写入你的清理逻辑:关闭文件、释放资源、记录日志等 echo "Running cleanup procedures...\n"; exit(0); } // 注册SIGHUP信号处理,禁用SA_RESTART,让阻塞调用被中断后不再重启 pcntl_signal(SIGHUP, 'cleanup_and_exit', false); // 额外注册SIGTERM,兼容部分终端关闭时发送的信号类型 pcntl_signal(SIGTERM, 'cleanup_and_exit', false); // 等待用户输入,收到信号时fgets会被中断并返回false $input = fgets(STDIN); // 若信号触发了退出标记,执行清理退出 if ($exitTriggered) { cleanup_and_exit(); } // 正常输入后的逻辑(如果需要) echo "Input received: $input\n";
验证方式
执行xterm -e php test.php,点击XTerm右上角关闭按钮,脚本会自动执行清理逻辑并终止进程,窗口正常关闭。
内容的提问来源于stack exchange,提问作者user20986345
相关产品推荐
相关产品推荐

