Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fork in Coroutine (Swoole\Error: must be forked outside the coroutine) #2716

Closed
kcloze opened this issue Jul 27, 2019 · 11 comments
Closed

Fork in Coroutine (Swoole\Error: must be forked outside the coroutine) #2716

kcloze opened this issue Jul 27, 2019 · 11 comments
Labels

Comments

@kcloze
Copy link

kcloze commented Jul 27, 2019

swoole 4.4.2 默认开启了协程,不允许在协程环境下 Swoole\Process->start(),造成之前的代码不兼容,有什么好的办法?全局禁用协程也不行

swoole-jobs之前基于\Swoole\Timer::tick下调用Swoole\Process实现,代码见这里:
[Swoole\Timer::tick]](https://github.com/kcloze/swoole-jobs/blob/master/src/Process.php#L252)
[Swoole\Process](https://github.com/kcloze/swoole-jobs/blob/master/src/Process.php#L152

)

@kcloze kcloze changed the title PHP Fatal error: Uncaught Swoole\Error: must be forked outside the coroutine in Swoole\Process->start() \Swoole\Timer::tick下执行Swoole\Process,PHP Fatal error: Uncaught Swoole\Error: must be forked outside the coroutine in Swoole\Process->start() Jul 27, 2019
@twose
Copy link
Member

twose commented Jul 27, 2019

Swoole\Coroutine::set(['enable_coroutine' => false]);

@twose twose closed this as completed Jul 27, 2019
@twose twose added the question label Jul 27, 2019
@kcloze
Copy link
Author

kcloze commented Jul 27, 2019

Swoole\Coroutine::set(['enable_coroutine' => false]);

这个方法无效,测试了几种方法:
无效

  • Swoole\Coroutine::set(['enable_coroutine' => false]);

  • ini_set('swoole.enable_coroutine','Off');

有效

  • 修改php.ini 增加 swoole.enable_coroutine = 'Off'

@kcloze
Copy link
Author

kcloze commented Jul 28, 2019

问题没解决就关了呢?

@twose
Copy link
Member

twose commented Jul 28, 2019

Sorry, 前面的回答写错了, 由于现在推全协程, 所以只能通过老的异步API或是php.ini关闭, 异步API是swoole_async_set(['enable_coroutine' => false]), 推荐使用你指出的php.ini配置的方法
这块内容有专门的文档和RFC:
https://wiki.swoole.com/wiki/page/949.html
https://wiki.swoole.com/wiki/page/352.html

@kcloze
Copy link
Author

kcloze commented Jul 28, 2019

那就是不能在运行时灵活关闭协程,这会影响部署(其他swoole 4应用就不能同时部署),能否给用户运行时关闭协程的开关呢?

@Yurunsoft
Copy link
Member

协程不能开进程,确实很难受

@twose
Copy link
Member

twose commented Jul 29, 2019

@kcloze
swoole_async_set(['enable_coroutine' => false])就是运行时的开关,协程外可以fork, 协程内多进程fork会产生安全问题
设计上可以专门部署一个manager进程来负责fork, 而不是工作进程动态fork

@huangzhhui
Copy link
Contributor

@kcloze
swoole_async_set(['enable_coroutine' => false])就是运行时的开关,协程外可以fork, 协程内多进程fork会产生安全问题
设计上可以专门部署一个manager进程来负责fork, 而不是工作进程动态fork

那其实 Swoole 是不是就可以这样去处理?如果在协程内 fork 就改成非 Worker 进程 fork ?

@twose
Copy link
Member

twose commented Jul 29, 2019

不行 不同进程上下文不一样 需要自己设计

就和SWOOLE_PROCESS的模式一样 专门有个manager进程去fork,但是一些预备工作要在start之前做好;如果是动态fork,就不是很好把控,可能一些工作做到了一半fork了,复杂的环境下,不一定能正确清理,不清理直接fork肯定会产生意料之外的问题

还有一种是使用exec,上下文无关的,安全的fork,但是不是很灵活

@twose twose changed the title \Swoole\Timer::tick下执行Swoole\Process,PHP Fatal error: Uncaught Swoole\Error: must be forked outside the coroutine in Swoole\Process->start() Fork in Coroutine (Swoole\Error: must be forked outside the coroutine) Jul 29, 2019
@hezll
Copy link

hezll commented Aug 9, 2019

楼上写的3种办法都没有成功,老版本请用如下代码设置。
https://wiki.swoole.com/wiki/page/p-4.0.1.html

$http = new swoole_http_server('127.0.0.1', 9501);
$http->set([
'enable_coroutine' => false, // close build-in coroutine
]);

这样应该也能够解决灵活部署或者多服务并存的问题;

swoole

swoole support => enabled
Version => 1.10.2

升级成功

php --ri swoole

swoole

Swoole => enabled
Author => Swoole Team [email protected]
Version => 4.4.0

@kcloze
Copy link
Author

kcloze commented Aug 9, 2019

swoole-jobs的多进程模块,没有用到http server

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants