swoole mysql null_在协程里使用MySQL连接池出现must be called in the coroutine的问题

`<?php

use Swoole\Coroutine\Channel;

use Swoole\Process;

class MyProcess

{

protected $chan;

protected $client;

private $swooleProcess;

private $processName;

private $async = null;

private $args = [];

final function __construct(string $processName,array $args = [],$async = true)

{

$this->async = $async;

$this->args = $args;

$this->processName = $processName;

$this->swooleProcess = new \swoole_process([$this,'__start']);

}

public function getProcess():Process

{

return $this->swooleProcess;

}

function __start(Process $process)

{

if(PHP_OS != 'Darwin'){

$process->name($this->getProcessName());

}

if (extension_loaded('pcntl')) {

pcntl_async_signals(true);

}

$this->run($this->swooleProcess);

}

public function getProcessName()

{

return $this->processName;

}

public function run(Process $process)

{

$this->addTick(2000,function(){

\go(function (){

echo "\n\nCurrent Coroutine id is : ".\Swoole\Coroutine::getuid() . "\n";

//直接运行代码,没有写捕获异常逻辑

$this->runSomeCode();

});

});

}

public function addTick($ms,callable $call):?int

{

return self::loop(

$ms,$call

);

}

public static function loop($microSeconds,callable $func,$args = null){

global $server;

$new = function (...$args)use($func){

try{

call_user_func($func,...$args);

}catch (\Throwable $throwable){

echo $throwable->getMessage();

}

};

return $server->tick($microSeconds,$new,$args);

}

//执行逻辑代码

protected function runSomeCode()

{

//正常逻辑代码

try {

//定时执行,easyswoole的AbstractPool类有定时回收闲置连接池,测试代码只是模拟一下问题,定位是这里如果逻辑出现一次错误后,此处后面执行就会频繁报错\Swoole\Coroutine\Channel::pop(): must be called in the coroutine.

swoole_timer_tick(2000,function(){

echo "pop from channel\n";

$this->chan->pop();

});

$this->getPool();

mt_srand();

//随机一次抛出异常

$rand = mt_rand(1,3);

echo "current rand is : ".$rand."\n";

//此处是为了模拟多次情况下,其中某一次不正常的情况

if ($rand != 3) {

var_dump('execute some logic');

} else {

throw new \Exception("some error");

}

} catch (\Throwable $throwable) {

throw $throwable;

}

}

protected function getPool()

{

$this->chan = new Channel(5);

$this->chan->push('test');

return $this->chan->pop();

}

}

$server = new \Swoole\Server('127.0.0.1', '9501', SWOOLE_PROCESS, SWOOLE_SOCK_UDP);

$server->set([

'log_file' => '/tmp/swoole.log',

// 'daemonize'=> 1

]);

$server->on('packet', function () { });

$server->addProcess((new MyProcess('test'))->getProcess());

$server->start();

?>

`

说明:

1.这里的代码,只是精简摘写部分easyswoole框架的代码

如果捕获抛出的异常(easyswoole连接超时会抛一个异常),不会有这种问题,但如果代码层级很深,很复杂的逻辑有遗漏捕获异常的情况下,而且逻辑里面有定时逻辑,每次定时执行时就出现这种问题,只能重新启动server了;

提这个issue,主要是想排查是不是因为swoole_time_tick由于没有捕获异常,而导致后续持续报这种Fatal error: Swoole\Coroutine\Channel::pop(): must be called in the coroutine.这种错误

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值