优雅地关闭PHP应用程序

优雅地关闭PHP应用程序,php,reactphp,Php,Reactphp,这个问题很相关,但有点笼统 例如,我有一个缓慢的I/O操作: 当我运行$loop->run()时我希望在某个点停止它,例如,在接受N个请求后,通过计时器停止,或者在任何其他事件(如pcntl_信号)或数据断言后停止,如示例所示 挑战是在退出之前完成所有已开始的工作,我不知道如何实现 在服务器控制台中,我有: Socket server listening on port 4000. You can connect to it by running: telnet localhost 4000

这个问题很相关,但有点笼统

例如,我有一个缓慢的I/O操作:

当我运行
$loop->run()时
我希望在某个点停止它,例如,在接受N个请求后,通过计时器停止,或者在任何其他事件(如
pcntl_信号
)或数据断言后停止,如示例所示

挑战是在退出之前完成所有已开始的工作,我不知道如何实现

在服务器控制台中,我有:

Socket server listening on port 4000.
You can connect to it by running: telnet localhost 4000
exited
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
1
2
3
4
5
> 1
> 2
42
Connection closed by foreign host.
在客户端控制台中,我有:

Socket server listening on port 4000.
You can connect to it by running: telnet localhost 4000
exited
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
1
2
3
4
5
> 1
> 2
42
Connection closed by foreign host.
其中,以1秒的间隔输入1,2,3,4,5

相反,我希望看到这样的情况:

Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
1
2
3
4
5
> 1
> 2
42
> 3
6
> 4
> 5
Connection closed by foreign host.

如评论中所述,要优雅地退出,您需要跟踪正在运行的流程,并仅在所有流程完成时停止循环:

$socket->on('connection',函数($conn)use($loop){
$processs=new SplObjectStorage();
$stop=false;
$conn->on('data',函数($data)使用($conn,$loop,$processs,&$stop){
如果('42'==修剪($data)){
$stop=true;
如果(!$processs->count()){
$loop->stop();
}
}
如果($stop){
返回;
}
$process=new React\ChildProcess\process('sleep 5;echo'.$data);
$processs->attach($process);
$process->on('exit',函数()使用($process,$processs,&$stop,$loop){
$processs->detach($process);
如果($stop&!$processs->count()){
$loop->stop();
}
});
$loop->addTimer(0.001,函数($timer)使用($process,$conn){
$process->start($timer->getLoop());
$process->stdout->on('data',function($output)use($conn){
如果($output&&'42'!==trim($output)){
$conn->write(“>$output”);
}
});
});
});
});

根据您的处理方式,您需要一个能够访问
$loop
的回调,然后只需调用
$loop->stop()
,即可believe@EliasVanOotegem:
$loop->stop()
停止循环。我已经更新了这个问题,让它更清楚一点,我需要循环在退出脚本之前完成所有启动的作业。因此,首先断开套接字,当队列为空时,停止循环,进程将退出。但是,你的进程不会挂起的保证在哪里?@N.B.谢谢,这是有道理的。你知道如何检查队列是否为空吗?进程可以随时挂起,它不是主题。可以在SIGKILL上立即退出。现在的挑战是在SIGTERM上优雅地退出。谢谢尤金,这正是我最终找到的解决办法。我不认为数据处理函数是保存循环管理代码的正确位置,但似乎没有更好的方法=(好的,更好的方法是发出您自己的“已完成”事件,并将带有循环管理逻辑的回调附加到它。