php 7.3 event 扩展 loop直接退出 其实已经添加了事件

1. 运行环境

php 7.3 cli模式 debian docker容器内部

1). 当前使用的 Laravel 版本?

多进程编程
//: <> (使用 php artisan --version 命令查看)

2). 当前使用的 php/php-fpm 版本?

PHP 版本:

php-fpm 版本:

3). 当前系统

4). 业务环境

5). 相关软件版本

2. 问题描述?

在串行调用时候可以正常的loop 进入事件循环代码如下

php 7.3 event 扩展 loop直接退出 其实已经添加了事件

![php 7.3 event 扩展 loop直接退出 其实已经添加了事件]
php 7.3 event 扩展 loop直接退出 其实已经添加了事件

换个写法就不行了,进程直接执行完,也没有什么报错,无法进入事件循环

php 7.3 event 扩展 loop直接退出 其实已经添加了事件

php 7.3 event 扩展 loop直接退出 其实已经添加了事件
有了解libevent编程的大佬帮忙看下嘛,不胜感激!

3. 您期望得到的结果?

4. 您实际得到的结果?

《L05 电商实战》
从零开发一个电商项目,功能包括电商后台、商品 & SKU 管理、购物车、订单管理、支付宝支付、微信支付、订单退款流程、优惠券等
《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
最佳答案

loop() 方法的调用是 EventBase 类的,第二种写法是对的

3年前 评论
echo_dump (作者) 3年前
jjawesome (楼主) 3年前
jjawesome (楼主) 3年前
jjawesome (楼主) 3年前
echo_dump (作者) 3年前
讨论数量: 11

loop() 方法的调用是 EventBase 类的,第二种写法是对的

3年前 评论
echo_dump (作者) 3年前
jjawesome (楼主) 3年前
jjawesome (楼主) 3年前
jjawesome (楼主) 3年前
echo_dump (作者) 3年前

第二种写法应该也没问题,创建一个资源描述符 fd 的事件对象 \Event$event->add() 加入事件监听,由事件驱动内核 $eventBase->loop() 调度挂起事件监听。可能需要检查,要监听的 $socket 是否是个有效的资源描述符,也就是此步是否创建成功 $socket = stream_socket_server(...)

3年前 评论
jjawesome (楼主) 3年前

来看几段代码, 猜想一下运行结果,哪些会进入事件循环,哪些会直接退出?

示例一

<?php

$eventbase = new \EventBase();

$eventbase->loop();

示例二

<?php

$eventbase = new \EventBase();

$socket = stream_socket_server('tcp://0.0.0.0:6000', $errno, $errmsg);
$event = new \Event($eventbase, $socket, \Event::READ | \Event::PERSIST, function () {
    echo 'event callback...' . PHP_EOL;
});
$event->add();

$eventbase->loop();

示例三

<?php

$eventbase = new \EventBase();

$socket = stream_socket_server('tcp://0.0.0.0:6000', $errno, $errmsg);
$event = new \Event($eventbase, $socket, \Event::READ | \Event::PERSIST, function () {
    echo 'event callback...' . PHP_EOL;
});
$event->add();

unset($event);

$eventbase->loop();

示例四

<?php 

$eventbase = new \EventBase();

function addEvent(&$eventbase){
    $socket = stream_socket_server('tcp://0.0.0.0:6000', $errno, $errmsg);
    $event = new \Event($eventbase, $socket, \Event::READ | \Event::PERSIST, function () {
        echo 'event callback...' . PHP_EOL;
    });
    $event->add();
}
addEvent($eventbase);

$eventbase->loop();

示例五

<?php 

$eventbase = new \EventBase();
$event = null;

function addEvent(&$eventbase, &$event){
    $socket = stream_socket_server('tcp://0.0.0.0:6000', $errno, $errmsg);
    $event = new \Event($eventbase, $socket, \Event::READ | \Event::PERSIST, function () {
        echo 'event callback...' . PHP_EOL;
    });
    $event->add();
}
addEvent($eventbase, $event);

$eventbase->loop();

答案是:示例一示例三示例四直接退出,示例二示例五进入循环。
分析几个示例的差异:
示例一,没有添加Event,loop直接结束
示例二,添加Event后,正常进入loop
示例三,添加Event后,将其unset掉,loop直接结束
示例四,使用函数封装添加Event逻辑,loop直接结束
示例五,使用函数封装添加Event逻辑,但用变量event保存了Event对象,正常进入loop

大致得出以下结论:

  1. 当EventBase监听的Events为空时,loop直接结束
  2. 当EventBase监听的Event被回收后,loop直接结束
  3. 对于函数而言,函数直接后,函数作用域内的临时变量会被回收

我的理解是,能正常loop的条件:EventBase监听的Events不能为空,EventBase监听的Event不能被回收。我猜测可能Event扩展 Event->add() 时 EventBase 保存的是Event对象的引用,但在PHP中由于没有其它地方引用变量导致被回收,loop时发现Event并不存在所以就直接结束了。

1年前 评论
jjawesome (楼主) 1年前
jjawesome (楼主) 1年前

讨论应以学习和精进为目的。请勿发布不友善或者负能量的内容,与人为善,比聪明更重要!