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. 您实际得到的结果?

《L04 微信小程序从零到发布》
从小程序个人账户申请开始,带你一步步进行开发一个微信小程序,直到提交微信控制台上线发布。
《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
最佳答案

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

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

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

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

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

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

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

示例一

<?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年前

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