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

《L02 从零构建论坛系统》
以构建论坛项目 LaraBBS 为线索,展开对 Laravel 框架的全面学习。应用程序架构思路贴近 Laravel 框架的设计哲学。
《L01 基础入门》
我们将带你从零开发一个项目并部署到线上,本课程教授 Web 开发中专业、实用的技能,如 Git 工作流、Laravel Mix 前端工作流等。
最佳答案

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 并不存在所以就直接结束了。

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