首页
下载
文档
社区
视频
捐赠
源代码
赞助商
AOT 编译器
AI 助理
商业产品
PHP AOT 原生编译器
Swoole-Compiler 代码加密器
CRMEB 新零售社交电商系统
登录
注册
全部
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
发表新帖
关于 process 子进程的问题
### 问题描述 在进程中 创建子进程 报错 must be forked outside the coroutine 用的hyperf 框架 主进程 已经开启了协程 ### Swoole版本,PHP版本,以及操作系统版本信息 - swoole 4.5.10 - php 7.4.16 - docker Alpine ### 相关代码 ```php class ExecProcess extends AbstractActiveMessageProcess { public function handle(): void { go(function () { SwooleProcess::signal(SIGCHLD, function ($sig) { //必须为false,非阻塞模式 while ($ret = SwooleProcess::wait(false)) { echo "子进程 PID : {$ret['pid']} 退出\n"; } }); }); while (true) { $message = $this->sockMsg->pop(); $this->addExec($message); } } private function addExec($data) { $process = new SwooleProcess(function (SwooleProcess $worker) use ($data) { $worker->exec($data['command'], $data['args']); }, true, 1, true); // 需要启用标准输入输出重定向 $process->start(); } } ``` ### 你期待的结果是什么?实际看到的错误信息又是什么? - 子进程无法启动 - 报错 must be forked outside the coroutine
发布于5年前 · 5 次浏览 · 来自
提问
nicoi
### 问题描述 在进程中 创建子进程 报错 must be forked outside the coroutine 用的hyperf 框架 主进程 已经开启了协程 ### Swoole版本,PHP版本,以及操作系统版本信息 - swoole 4.5.10 - php 7.4.16 - docker Alpine ### 相关代码 ```php class ExecProcess extends AbstractActiveMessageProcess { public function handle(): void { go(function () { SwooleProcess::signal(SIGCHLD, function ($sig) { //必须为false,非阻塞模式 while ($ret = SwooleProcess::wait(false)) { echo "子进程 PID : {$ret['pid']} 退出\n"; } }); }); while (true) { $message = $this->sockMsg->pop(); $this->addExec($message); } } private function addExec($data) { $process = new SwooleProcess(function (SwooleProcess $worker) use ($data) { $worker->exec($data['command'], $data['args']); }, true, 1, true); // 需要启用标准输入输出重定向 $process->start(); } } ``` ### 你期待的结果是什么?实际看到的错误信息又是什么? - 子进程无法启动 - 报错 must be forked outside the coroutine
赞
0
收藏
提问
分享
讨论
建议
公告
开发框架
CodeGalaxy
登录
后参与评论
评论
2021-03-18
鲁飞
不能在协程中使用,可以用这个个https://wiki.swoole.com/#/coroutine/system?id=waitsignal
赞
0
回复
2021-03-19
序冢
你要明白exec一个重要的特性,进程空间里代码放在.text数据段,如果你调用exec,当前进程的所有.text数据段(代码段)都会被替换,多进程的话有良好的隔离,协程实质还是在同一个进程,用的一个.text数据段,不像fork+exec这种可以再分离一个.text数据段,所以说肯定不能在协程里用exec
赞
0
回复
2021-03-20
nicoi
回复
序冢
在下面发了 麻烦大佬看看
赞
0
回复
2021-03-19
nicoi
我的代码贴的 可能有问题 ```php class ExecProcess extends AbstractActiveMessageProcess { public function handle(): void { while (true) { $message = $this->sockMsg->pop(); $this->addExec($message); } } private function addExec($data) { $process = new SwooleProcess(function (SwooleProcess $worker) use ($data) { $worker->exec($data['command'], $data['args']); }, true, 1, true); // 需要启用标准输入输出重定向 $process->start(); } } ``` 上面那个 监听只是为了测试一下 进程是不是启动了 主要的报错是这个子进程无法启动 ```php $process->start(); ``` 这一步就报错了
赞
0
回复
2021-03-22
序冢
回复
nicoi
swoole有协程exec的api Swoole\Coroutine\System::exec(string $cmd): array 用这个,其实也是开了进程
赞
0
回复
2021-03-23
nicoi
回复
序冢
嗯嗯 已经解决了 主进程开了协程就 不能再开子进程了 是想实时获取 命令输出的 现在只能写入 文件再去读取了
赞
0
回复