$serv->on("WorkerStart", function () use ($process) {
while(true) {
//底层使用了`reactor_write`异步发送,会将该`socket`设置为非阻塞模式
$process->write("hello");
//这里会理解返回 false,错误码为 EAGAIN
$msg = $process->read();
}
});
问题解决
可以显式地设置process->pipe管道为阻塞或非阻塞而不是底层根据reactor进行判断
默认为阻塞IO
调用Event::add添加事件时会自动将管道转为非阻塞(现存逻辑)
$serv->on("WorkerStart", function () use ($process) {
//设置为阻塞模式
$process->setBlocking(true);
while(true) {
$process->write("hello");
$msg = $process->reqd();
}
});
use Swoole\Event;
$serv->on("WorkerStart", function () use ($process) {
//设置为非阻塞模式
$process->setBlocking(false);
Event::add($process->pipe, function () use ($process) {
$msg = $process->read();
});
});
问题描述
底层在
process->write
是根据当前有没有reactor
来判断是否启用非阻塞的,这个存在严重的问题。比如在 worker 进程中 write,就会用 reactor_write 异步发送,但是必须设置 pipe 为nonblock
,如果 worker 进程中又有代码是阻塞循环 process->read ,那么就会出现死循环。因此底层设计上根据当前进程是否有
reactor
的思路是存在缺陷的。演示代码
问题解决
process->pipe
管道为阻塞或非阻塞而不是底层根据reactor
进行判断IO
Event::add
添加事件时会自动将管道转为非阻塞(现存逻辑)