× 警告!旧版文档已经暂停维护,请查看新版文档。点击前往新版文档

退出协程

在Swoole低版本中, 协程中使用exit强行退出脚本会导致内存错误导致不可预期的结果或coredump, 在Swoole服务中使用exit会使整个服务进程退出且内部的协程全部异常终止导致严重问题

Swoole长期以来一直禁止开发者使用exit, 但开发者可以使用抛出异常这种非常规的方式, 在顶层catch来实现和exit相同的退出逻辑

4.2.2版本及以上允许脚本(未创建http_server)在只有当前协程的情况下exit退出

Swoole4.1.0版本及以上直接支持了在协程, 服务事件循环中使用PHP的exit, 此时底层会自动抛出一个可捕获的Swoole\ExitException, 开发者可以在需要的位置捕获并实现与原生PHP一样的退出逻辑.


Swoole\ExitException继承于Exception且新增了两个方法getStatusgetFlags:

类原型:

namespace Swoole;
class ExitException extends \Exception
{
    public function getStatus():mixed
    public function getFlags():int
}

函数原型

public function getStatus():mixed

获取exit($status)退出时的传入的status参数, 支持任意的变量类型

public function getFlags():int

获取exit退出时所处的环境信息掩码, 目前有以下掩码

SWOOLE_EXIT_IN_COROUTINE //协程中退出
SWOOLE_EXIT_IN_SERVER //服务中退出

使用方法

基本使用

function route()
{
    controller();
}

function controller()
{
    your_code();
}

function your_code()
{
    co::sleep(.001);
    exit(1);
}

go(function () {
    try {
        route();
    } catch (\Swoole\ExitException $e) {
        assert($e->getStatus() === 1);
        assert($e->getFlags() === SWOOLE_EXIT_IN_COROUTINE);
        return;
    }
});

带状态码的退出

<?php
$exit_status = 0;
go(function () {
    try {
        exit(123);
    } catch (\Swoole\ExitException $e) {
        global $exit_status;
        $exit_status = $e->getStatus();
    }
});
swoole_event_wait();
exit($exit_status);

关闭内置协程, 允许在异步中退出

swoole_async_set([
    'enable_coroutine' => false
]);
swoole_timer_after(1000, function () {
    exit;
});