Releases: swoole/swoole-src
v6.1.3
Release Notes
🐛 Bug Fixes
HTTP/2 Server
- Fixed Safari Compatibility Issue: Resolved a flow control compatibility issue when the HTTP/2 server sends large files to Safari browsers.
- Fixed Data Race in Cached
DateResponse Header: Fixed a data race condition in the cachedDateresponse header for the HTTP/2 server in multi-threaded mode. - Fixed
package_max_lengthConfiguration Not Taking Effect:- The server now returns a
413 Payload Too Largeerror if theContent-Lengthin the receivedHEADERSframe exceeds the configured value. - The server sends an
HTTP/2 RST_STREAMframe to terminate the stream if the total length of consecutively receivedDATAframes exceeds the configured value.
- The server now returns a
- Fixed Memory Out-of-Bounds in Multi-threaded Coroutine Mode: Resolved a memory out-of-bounds issue when enabling
enable_reuse_portin the multi-threaded coroutine version of the HTTP/2 server. - Fixed TLS Variable Destruction Issue: Fixed a
double freeissue occurring during the destruction of TLS (Thread Local Storage) variables upon thread exit in the multi-threaded HTTP/2 server.
Redis Server
- Fixed packet assembly anomalies in
Redis\Server::format()when processing large strings.
WebSocket Server
- Fixed Control Frame Data Contamination: Resolved an issue where automatically replied
ping/pong/closecontrol frames from the WebSocket server carried residual data from previous text or binary frames due to uncleared buffers.
Multi-threading Related
- Fixed Data Race in
swoole_get_task_tmpdir(): Resolved a data race condition when calling this function in a multi-threaded environment. - Fixed Memory Out-of-Bounds Access in Runtime Hooks: Fixed memory out-of-bounds access triggered when setting runtime hooks in a multi-threaded environment.
⚠️ Important Change: Runtime hooks can now only be set in the main thread and must be configured before creating any child threads.
Platform Compatibility
- Fixed FreeBSD Compilation Failure: Resolved compilation failures on FreeBSD systems.
✨ Enhancements
- Added Android Platform Support: Improved compatibility with the Android platform; now supported in Termux environments.
- Synchronized Updates from PHP 8.x curl Module: Adapted relevant updates from the
curlextension in PHP versions 8.1, 8.2, and 8.3.
Note: This update includes several critical fixes for multi-threaded mode. Users utilizing multi-threaded mode are strongly advised to upgrade as soon as possible.
更新记录
🐛 Bug 修复
HTTP/2 服务器
- 修复 Safari 浏览器兼容性问题:解决 HTTP/2 服务器在向 Safari 浏览器发送大文件时的流量控制兼容性问题
- 修复 Date 响应头缓存的数据竞争:解决多线程模式下 HTTP/2 服务器的
Date响应头缓存存在的数据竞争问题 - 修复
package_max_length配置未生效:- 当接收的
Header帧中Content-Length超过配置值时,服务器将返回413 Payload Too Large错误 - 当连续接收的
Data帧总长度超过配置值时,服务器将发送HTTP/2 RST_STREAM帧终止流
- 当接收的
- 修复多线程协程模式下的内存越界:解决多线程模式协程版
HTTP/2服务器开启enable_reuse_port时发生的内存越界问题 - 修复
TLS变量销毁问题:解决多线程模式HTTP/2服务器在线程退出时TLS (Thread Local Storage)变量销毁时发生的double free问题
Redis 服务器
- 修复
Redis\Server::format()处理大字符串出现的组包异常问题
WebSocket 服务器
- 修复控制帧数据污染问题:解决
WebSocket服务端自动回复的ping/pong/close控制帧因未清空缓存,导致携带前一个文本帧或二进制帧残留数据的问题
多线程相关
- 修复
swoole_get_task_tmpdir()数据竞争:解决多线程环境下调用该函数时存在的数据竞争问题 - 修复运行时钩子的内存越界访问:解决多线程环境下设置运行时钩子时触发的内存越界访问问题
⚠️ 重要变更:运行时钩子现在仅允许在主线程中设置,且必须在创建任何子线程之前完成设置
平台兼容性
- 修复 FreeBSD 编译失败:解决在 FreeBSD 系统下的编译失败问题
✨ 功能增强
- 新增 Android 平台支持:提升在 Android 平台的兼容性,现已支持在 Termux 环境下运行
- 同步 PHP 8.x curl 模块更新:适配 PHP 8.1、8.2 及 8.3 版本中
curl扩展的相关更新
注意事项:本次更新包含多项多线程模式下的关键修复,建议使用多线程模式的用户尽快升级。
v6.1.2
- No longer throw warnings when failing to set the
socketreceive/send buffer size - Fixed an issue in
Swoole\Http\Serverwhere theonClosecallback might execute beforeonRequestwhen handlingHTTP2requests, leading to a use-after-free problem - Optimized the
getSocket()method by duplicating the file descriptor when exporting thephp socketsresource object, preventingphp socketsfrom affecting thesocketheld bySwooleupon closure - Fixed a memory leak issue in
Swoole\Async\Client - Fixed an issue where
Swoole\Coroutine\Http\ClientofIPv6type could not useSocks5proxy - Synchronized updates to adapt to relevant changes in the
CURLextension inPHP 8.4 - Added the
async.file://file protocol, which allows enabling coroutine scheduling for specific file operations even when global file coroutine support is disabled
use function Swoole\Coroutine\run;
// Disable global file coroutine support but enable coroutine operations for specific files via the `async.file://` protocol
Swoole\Runtime::enableCoroutine(SWOOLE_HOOK_ALL & ~SWOOLE_HOOK_FILE);
run(function() {
$fp = fopen("async.file:///home/test", "r");
fwrite($fp, "data");
fclose($fp);
$content = file_get_contents("async.file:///home/test.txt");
});This feature is designed for scenarios where global file system coroutine HOOK is disabled, but asynchronous read/write scheduling is required for specific file operations.
简体中文
- 设置
socket接收/发送缓冲区尺寸失败时不再抛出警告 - 修复
Swoole\Http\Server处理HTTP2请求时,onClose回调可能先于onRequest执行,导致释放后使用(use-after-free)的问题 - 优化
getSocket()方法,导出php sockets资源对象时复制文件描述符,避免php sockets关闭时影响Swoole持有的socket - 修复
Swoole\Async\Client内存泄漏问题 - 修复
IPv6类型Swoole\Coroutine\Http\Client无法使用Socks5代理的问题 - 同步适配
PHP 8.4中CURL扩展的相关更新 - 新增
async.file://文件协议,支持在未开启全局文件协程化时,对指定文件操作启用协程调度
use function Swoole\Coroutine\run;
// 禁用全局文件协程化,但可通过 `async.file://` 协议对特定文件启用协程操作
Swoole\Runtime::enableCoroutine(SWOOLE_HOOK_ALL & ~SWOOLE_HOOK_FILE);
run(function() {
$fp = fopen("async.file:///home/test", "r");
fwrite($fp, "data");
fclose($fp);
$content = file_get_contents("async.file:///home/test.txt");
});该特性用于在禁用全局文件系统协程 HOOK后,对部分文件操作进行异步读写调用的场景。
v6.1.1
- Fixed a compilation failure caused by missing
zlibdependency. - Optimized the resource management logic in the
curlmodule to prevent use-after-free risks. - Resolved the absence of
fdatasyncon macOS systems. - Improved the log output format for coroutine deadlock detection.
简体中文
- 修复因为缺少
zlib依赖导致编译失败的问题。 - 优化
curl模块的资源管理逻辑,以规避释放后再次使用的风险。 - 修复
macos系统没有fdatasync的问题。 - 优化协程死锁检测日志输出格式。
v6.1.0
Major Changes in Swoole 6.1.0
1. Introduction of "Standard Library Extensions" - Revolutionary Syntax Enhancements
This is the most eye-catching feature at the language level in this update, allowing object-oriented operations on basic types.
- Object-Oriented Basic Types: Methods can be called directly on variables of basic types like
string,array, andstream(e.g.,$text->length()->lower()), greatly improving code readability and development experience. - Typed Arrays: Introduced the
typed_arraysyntax, allowing constraints on key and value types (e.g.,<int, string>), with type checks performed on write operations, enhancing code robustness.
2. A Major Leap in Underlying Architecture and Stability
This version invests heavily in code quality and stability, laying a solid foundation for future development.
- Significant Increase in Test Coverage to 86%: By systematically adding test cases, potential errors are greatly reduced, improving the overall reliability and maintainability of the project.
- Large-Scale Code Refactoring and Static Analysis: Refactored multiple core modules like Reactor, SSL, and Socket, and used
clang-tidyfor code standardization, significantly improving code quality and performance.
3. Major Simplification and Unification of the Lock API
A groundbreaking refactoring of the core component for concurrent programming – the lock.
- API Simplification: Removed methods like
lockwaitandtrylock, retaining only three core methods –__construct,lock, andunlock– forSwoole\Coroutine\Lock,Swoole\Lock, andSwoole\Thread\Lock. - Unified Behavior: The new API design is closer to PHP's native
flockfunction, reducing the learning curve, and uses standard constants likeLOCK_EX | LOCK_NBto implement advanced features such as non-blocking.
4. Enhanced Coroutine Capabilities and Fine-Grained Control
More flexible coroutine operation capabilities.
- Coroutine Cancellation Mechanism:
Swoole\Coroutine::cancel()now includes a$throw_exceptionparameter, allowing a catchableSwoole\Coroutine\CanceledExceptionto be thrown into the target coroutine upon cancellation, enabling safer and more controllable coroutine lifecycle management. - Coroutine State Isolation for Serialization Operations: Fixed the issue of global state isolation for serialize/unserialize in coroutine environments. Global variables related to serialization are now automatically saved and restored during coroutine switches, ensuring isolated serialization contexts for each coroutine.
5. Default HTTP Parser Upgrade, Websocket Feature Enhancements, and Platform Compatibility Improvements
Important improvements in performance and compatibility.
- llHTTP Enabled by Default: Replaced the old
http_parserwith the more performant and modernllhttp, improving the efficiency and reliability of HTTP processing. - WebSocket Feature Enhancements: Both client and server now support receiving fragmented messages, actively disconnecting (
disconnect), and sending Ping frames (ping), making the WebSocket protocol implementation more complete. - Deprecating Select, Embracing Poll: Completely deprecated the flawed
selectevent mechanism. On platforms that do not supportepoll/kqueue(like Cygwin),pollis now used by default, enabling support for a large number of concurrent connections on these platforms as well.
🎉 Standard Library Extensions
Swoole-Cli version 6.1 will add PHP standard library extension syntax, providing some additional new syntax while maintaining full compatibility with the official PHP syntax. These new extension syntaxes are all optional and do not affect existing PHP code. The standard library extension syntax will be implemented in the stdext module of ext-swoole.
swoole-cliusers can use it directly without any additional parameters.ext-swooleusers need to add--enable-swoole-stdextduring compilation to enable it.stdextcan be used inphp-cli,php-fpm,cli-http-server, andswoolemodes.
1. Object-Oriented Basic Types
Version 6.1 implements object-oriented encapsulation of array, string, and stream basic types, supporting method calls in an object-oriented style. Methods can be called directly on variables of these types.
The built-in methods for basic types actually still call the PHP standard library implementations. There is a one-to-one correspondence between the built-in methods and PHP's str_ or array_ series of functions. For example, $text->replace() corresponds to the str_replace function. The underlying layer only adjusts the function names, the parameter order for a few methods, and the parameter and return value types for a couple of methods. Please refer to the Swoole Documentation for details.
$text = 'Hello Swoole';
var_dump($text->length());
echo $text->lower()->replace("swoole", "php");
echo fopen("/tmp/test.log")->read(1024);2. Typed-Array Strongly Typed Arrays
Allows restricting array types, such as Map or ArrayList, and restricting the types of key and value. Supports multi-level nested formats. A typed array is still essentially an array type; the underlying layer only performs parameter checks on write operations. A typed array can be passed as an array to other functions or class methods.
$array = typed_array('<int, string>');
$array[1000] = "hello"; // Correct
$array[2000] = 2025; // Error, throws an exception✨ New Features
- llHTTP Default Parser: Starting from v6.1.0, Swoole uses the more performant
llhttpinstead ofhttp_parseras the default HTTP message parser. - Coroutine-based File Download:
Swoole\Coroutine\Http\Clientnow supports complete coroutine-based file download operations. - Asynchronous File Truncation: Added
iouring ftruncatesupport, expanding asynchronous file operation capabilities. Swoole\Coroutine::cancel()adds a$throw_exceptionparameter, supporting throwing an exception when canceling a coroutine.Swoole\Coroutine\Http\ClientandSwoole\Coroutine\Http\Servernow support receiving WebSocket fragmented messages.- Added
disconnectandpingmethods forSwoole\Coroutine\Http\ClientandSwoole\Coroutine\Http\Server. - Refactored
Swoole\Coroutine\Lock,Swoole\Lock, andSwoole\Thread\Lock, retaining only the__construct,lock, andunlockmethods, making usage closer tophp flock.
🐛 Bug Fixes
- Thread Mode Optimization:
- Fixed the issue where
hook_flagssettings became ineffective inSWOOLE_THREADmode. - Fixed the issue where the heartbeat thread held invalid pointers and accessed freed memory after worker threads restarted due to reaching the
max_requestlimit. - Fixed the issue of not supporting restarting
Taskprocesses individually. - Fixed an issue where
Swoole\Websocket\Servermight still trigger theonMessagecallback after a handshake failure or connection closure. - Fixed execution errors in
Swoole\Coroutine\Http\Servercaused by inconsistencies between function return value types and signatures. - Fixed the issue where
Swoole\Coroutine\Http\Serverdid not support enabling HTTP/2. - Fixed the timeout precision conversion issue in
Swoole\Lock::lockwait(). - Fixed the issue causing
ReactorEpoll::add(): failed to add eventwarnings when using the coroutine-basedcurlmodule, due toPHP 8compatibility adjustments and incomplete cleanup ofkeepaliveconnections. - Fixed the issue where
Swoole\Server::taskWaitMulti()could not be used in multi-threaded mode. - Fixed resource competition issues in
Swoole\Server::taskCo()in multi-threaded mode.
- Fixed the issue where
- Stability Improvements:
- Fixed the issue where synchronous processes (including manager and task processes) could not normally use
process::signal(). - Corrected the resource cleanup mechanism when worker processes exit abnormally.
- Resolved compilation failure issues on the Cygwin platform.
- Fixed the issue where curl with keepalive enabled could not reuse sockets.
- Improved the log component to resolve data consistency issues in multi-threaded mode.
- Fixed the compilation failure of the
io_uringfutexfeature onubuntu24.04. - Fixed the compilation failure on older Linux systems due to struct order assignment.
- Fixed the uninitialized
idproperty issue for directly instantiatedSwoole\Processobjects. - Fixed the missing
--enable-zstdoption in composer.json when compiling swoole withPIE. - Fixed the issue where
workerprocesses could not send signals to themanagerprocess due to insufficient permissions after specifying a user group.
- Fixed the issue where synchronous processes (including manager and task processes) could not normally use
- Compatibility Improvements:
- Fixed compatibility issues with
php_swoole_register_shutdown_functionunder PHP 8.5. - Corrected the handling of null parameters in
Swoole\Table::get().
- Fixed compatibility issues with
- Protocol Handling:
- Optimized the handling mechanism for duplicate fields in HTTP request and response headers to ensure correct merging.
- Fixed the issue where processing a client
Accept-Encoding: zlibrequest header would trigger an unknown compression method warning when the system lackedzlib.
❌️ Deprecations
- No longer supports the
selectevent mechanism.selectonly supports event monitoring for up to1024file descriptors and has serious flaws. On platforms that do not supportepoll/kqueue,pollwill be used as the event polling mechanism, allowing theCygwinplatform to also support a large number of concurrent connections. - In the
Swoole\Server::stop()method, the second parameter$waitEventhas been deprecated; please use thereload_asyncparameter instead.
🛠️ Architectural Optimizations
Version 6.1...
v6.1.0-rc2
✨ New Features
- Added the
$throw_exceptionparameter toSwoole\Coroutine::cancel(), enabling exceptions to be thrown when canceling a coroutine. Swoole\Coroutine\Http\ClientandSwoole\Coroutine\Http\Servernow support receiving WebSocket fragmented messages.- Added
disconnectandpingmethods toSwoole\Coroutine\Http\ClientandSwoole\Coroutine\Http\Server. - Refactored
Swoole\Coroutine\Lock,Swoole\Lock, andSwoole\Thread\Lock, retaining only the__construct,lock, andunlockmethods, making usage more aligned withphp flock.
🐛 Bug Fixes
- Fixed an issue where
Swoole\Websocket\Servermight still trigger theonMessagecallback after a handshake failure or connection closure. - Fixed execution errors in
Swoole\Coroutine\Http\Servercaused by mismatched return types and function signatures. - Fixed the issue where
Swoole\Coroutine\Http\Serverdid not support enabling HTTP/2. - Fixed the timeout precision conversion issue in
Swoole\Lock::lockwait(). - Fixed the
ReactorEpoll::add(): failed to add eventwarning when using the coroutine-basedcurlmodule, caused by PHP 8 compatibility adjustments and incomplete cleanup ofkeepaliveconnections.
🛠️ Internal Optimizations
- Upgraded the
Swoole libraryversion. - Disabled the
-Wdate-timewarning to resolve compilation errors when using Zig/Clang. - Removed PHP 8.0 related compatibility code.
- Added the
SWOOLE_ODBC_LIBSvariable inconfig.m4. - Ensured that
timespec.tv_nsecvalues are less than1,000,000,000to comply with POSIX standards.
⚠️ Notes
- This version is an RC (Release Candidate) and should only be used in testing environments. Do not deploy it in production.
- Starting from Swoole 6.1,
Swoole\Coroutine\Http\ClientandSwoole\Coroutine\Http\Serverwill automatically handle WebSocket control frames unlessopen_websocket_ping_frame,open_websocket_pong_frame, oropen_websocket_close_frameare explicitly set. Swoole\Coroutine::cancel()cannot cancel file coroutine operations. Forcibly canceling may cause segmentation faults.- If
--enable-iouringis enabled, a warning will be thrown if the kernel version orliburingversion does not meet the requirements. - The
Swoole\Websocket\Server::pushmethod will not automatically close the connection after sending a close frame. To close the connection, use theSwoole\Websocket\Server::disconnect()method. - When processing control frames, the Swoole protocol actively sets the FIN flag to 1 and ensures compression is not enabled (i.e., the RSV1 bit is 0). User settings for this will be ignored.
- When handling compression and sending of consecutive frames, Swoole delegates the responsibility of compression and data chunking to the application layer. Users must manually implement the relevant logic. Refer to the example below for details.
💡 API Changes
New Lock API
Function Prototypes
namespace Swoole\Coroutine {
class Lock {
public function __construct(bool $shared = false) {}
public function lock(int $operation = LOCK_EX): bool {}
public function unlock(): bool {}
}
}
namespace Swoole {
class Lock {
public function __construct(int $type = SWOOLE_MUTEX) {}
public function lock(int $operation = LOCK_EX, float $timeout = -1): bool {}
public function unlock(): bool {}
}
}
namespace Swoole\Thread {
class Lock {
public function __construct(int $type = SWOOLE_MUTEX) {}
public function lock(int $operation = LOCK_EX, float $timeout = -1): bool {}
public function unlock(): bool {}
}
}Usage Example
$lock = new Swoole\Lock;
$lock->lock(LOCK_EX | LOCK_NB, 0.5);
$lock->unlock();Canceling Coroutines
Co\run(function () {
$cid = Co\go(function () {
try {
while (true) {
System::sleep(0.1);
echo "co 2 running\n";
}
var_dump('end');
} catch (Swoole\Coroutine\CanceledException $e) {
var_dump('cancelled');
}
});
System::sleep(0.3);
Co::cancel($cid, true);
System::sleep(0.2);
echo "co 1 end\n";
});WebSocket Compression and Sending Consecutive Frames
Asynchronous Server
use Swoole\WebSocket\Server;
use Swoole\WebSocket\Frame;
$server = Server('127.0.0.1', 9502);
$server->set(['websocket_compression' => true]);
$server->on('message', function (Server $server, Frame $frame) {
$data1 = bin2hex(random_bytes(10 * 1024));
$data2 = bin2hex(random_bytes(20 * 2048));
$data3 = bin2hex(random_bytes(40 * 4096));
$context = deflate_init(ZLIB_ENCODING_RAW); // Stream compression
$server->push($frame->fd, deflate_add($context, $data1, ZLIB_NO_FLUSH), SWOOLE_WEBSOCKET_OPCODE_TEXT, SWOOLE_WEBSOCKET_FLAG_COMPRESS | SWOOLE_WEBSOCKET_FLAG_RSV1);
$server->push($frame->fd, deflate_add($context, $data2, ZLIB_NO_FLUSH), SWOOLE_WEBSOCKET_OPCODE_CONTINUATION, 0);
$server->push($frame->fd, deflate_add($context, $data3, ZLIB_FINISH), SWOOLE_WEBSOCKET_OPCODE_CONTINUATION, SWOOLE_WEBSOCKET_FLAG_FIN);
});
$server->start();Coroutine Server
use function Swoole\Coroutine\run;
use Swoole\Coroutine\Http\Server;
run(function() {
$server = new Server("127.0.0.1", 9502);
$server->set(['websocket_compression' => true]);
$server->handle('/', function ($request, $response) use ($data1, $data2, $data3) {
$response->upgrade();
$data1 = bin2hex(random_bytes(10 * 1024));
$data2 = bin2hex(random_bytes(20 * 2048));
$data3 = bin2hex(random_bytes(40 * 4096));
$context = deflate_init(ZLIB_ENCODING_RAW);
$response->push(deflate_add($context, $data1, ZLIB_NO_FLUSH), SWOOLE_WEBSOCKET_OPCODE_TEXT, SWOOLE_WEBSOCKET_FLAG_COMPRESS | SWOOLE_WEBSOCKET_FLAG_RSV1);
$response->push(deflate_add($context, $data2, ZLIB_NO_FLUSH), SWOOLE_WEBSOCKET_OPCODE_CONTINUATION, 0);
$response->push(deflate_add($context, $data3, ZLIB_FINISH), SWOOLE_WEBSOCKET_OPCODE_CONTINUATION, SWOOLE_WEBSOCKET_FLAG_FIN);
});
});Coroutine Client
use function Swoole\Coroutine\run;
use Swoole\Coroutine\Http\Client;
run(function() {
$client = new Client('127.0.0.1', 9502);
$client->set(['websocket_compression' => true]);
$ret = $client->upgrade('/');
$context = deflate_init(ZLIB_ENCODING_RAW);
$client->push(deflate_add($context, $data1, ZLIB_NO_FLUSH), SWOOLE_WEBSOCKET_OPCODE_TEXT, SWOOLE_WEBSOCKET_FLAG_COMPRESS | SWOOLE_WEBSOCKET_FLAG_RSV1);
$client->push(deflate_add($context, $data2, ZLIB_NO_FLUSH), SWOOLE_WEBSOCKET_OPCODE_CONTINUATION, 0);
$client->push(deflate_add($context, $data3, ZLIB_FINISH), SWOOLE_WEBSOCKET_OPCODE_CONTINUATION, SWOOLE_WEBSOCKET_FLAG_FIN);
});✨ 新功能
Swoole\Coroutine::cancel()新增$throw_exception参数,支持在取消协程时抛出异常。Swoole\Coroutine\Http\Client与Swoole\Coroutine\Http\Server现已支持接收 WebSocket 分块消息。- 为
Swoole\Coroutine\Http\Client和Swoole\Coroutine\Http\Server新增disconnect与ping方法。 - 重构
Swoole\Coroutine\Lock,Swoole\Lock和,Swoole\Thread\Lock,只保留__construct,lock和unlock方法,使用上更加贴近php flock。
🐛 问题修复
- 修复
Swoole\Websocket\Server在握手失败或连接关闭后,仍可能触发onMessage回调的问题。 - 修复
Swoole\Coroutine\Http\Server因函数返回值类型与签名不一致导致的执行错误。 - 修复
Swoole\Coroutine\Http\Server不支持启用 HTTP/2 的问题。 - 修复
Swoole\Lock::lockwait()超时时间精度转换问题。 - 修复因
PHP 8兼容性调整及keepalive连接清理不彻底,导致使用协程化curl模块时出现ReactorEpoll::add(): failed to add event警告的问题。
🛠️ 内部优化
- 升级
Swoole library版本。 - 禁用
-Wdate-time警告,解决使用 Zig/Clang 编译时的错误。 - 移除 PHP 8.0 相关兼容代码。
- 在
config.m4中新增SWOOLE_ODBC_LIBS变量。 - 确保
timespec.tv_nsec取值小于1,000,000,000,以符合 POSIX 标准规范。
⚠️ 注意事项
- 本版本为 RC(候选发布)版本,请仅在测试环境中使用,请勿在生产环境部署。
- 自 Swoole 6.1 起,
Swoole\Coroutine\Http\Client与Swoole\Coroutine\Http\Server将自动处理 WebSocket 控制帧,除非显式设置open_websocket_ping_frame、open_websocket_pong_frame或open_websocket_close_frame。 Swoole\Coroutine::cancel()无法取消文件协程化操作,强行取消可能导致段错误。- 若启用
--enable-iouring,在检测到内核版本或liburing版本不满足要求时,将抛出警告信息。 Swoole\Websocket\Server::push方法在发送关闭帧后不会自动关闭连接,如需关闭连接,请使用Swoole\Websocket\Server::disconnect()方法。Swoole协议在处理控制帧时,会主动设置 FIN 标志位为 1,并确保不启用压缩(即 RSV1 位为 0),用户对此的设置将被忽略。- 当处理连续帧的压缩和发送时,
Swoole将压缩与数据分块的职责移交至应用层,用户需手动实现相关逻辑。具体请看最下面的例子。
💡 API 变更
新的锁 API
函数原型
namespace Swoole\Coroutine {
class Lock {
public function __construct(bool $shared = false) {}
public function lock(int $operation = LOCK_EX): bool {}
public function unlock(): bool {}
}
}
namespace Swoole {
class Lock {
public function __construct(int $type = SWOOLE_MUTEX) {}
public function lock(int $operation = LOCK_EX, float $timeout = -1): bool {}
public function unlock(): bool {}
}
}
namespace Swoole\Thread {
class Lock {
public function __construct(int $type = SWOOLE_MUTEX) {}
public function lock(int $operation = LOCK_EX, float $timeout = -1): bool {}
public function unlock(): bool {}
}
}使用示例
$lock = new Swoole\Lock;
$lock->lock(LOCK_EX | LOCK_NB, 0.5);
$lock->unlock();取消协程
Co\run(function () {
$cid = Co\go(function () {
try {
while (true) {
System::sleep(0.1);
echo "co 2 running\n";
}
var_dump('end');
} catch (Swoole\Coroutine\CanceledException $e) {
var_dump('cancelled');
}
});
System::sleep(0.3);
Co::cancel($cid, true);
System::sleep(0.2);
echo "co 1 end\n";
});WebSocket 压缩和发送连续帧
异步服务端
``...
v6.1.0-rc1
Standard Library Extension
In version 6.1, Swoole-Cli will introduce extended syntax for the PHP standard library, providing additional new syntax while maintaining full compatibility with the official PHP syntax. These new extended syntax features are entirely optional and do not affect existing PHP code. The standard library extension syntax will be implemented in the stdext module of ext-swoole.
swoole-cliusers can use it directly without any additional parameters.ext-swooleusers need to add--enable-swoole-stdextduring compilation to enable it.stdextcan be used inphp-cli,php-fpm,cli-http-server, andswoolemodes.
1. Object-Oriented Basic Types
Version 6.1 implements object-oriented encapsulation of basic types such as array, string, and stream, supporting method calls in an object-oriented style. Built-in methods can be directly called on variables of these types.
The built-in methods for basic types still utilize the PHP standard library. These methods correspond one-to-one with PHP's str_ or array_ series functions. For example, $text->replace() corresponds to the str_replace function. The underlying implementation only adjusts function names, slightly modifies the parameter order for a few methods, and adjusts parameter and return value types for several others. For details, please refer to the Swoole Documentation.
$text = 'Hello Swoole';
var_dump($text->length());
echo $text->lower()->replace("swoole", "php");
echo fopen("/tmp/test.log")->read(1024);2. Typed-Array
Typed arrays can enforce type constraints, such as Map or ArrayList, and restrict the types of keys and values. Multi-level nested formats are supported. Typed arrays are still essentially array types, with parameter checks performed only during write operations. Typed arrays can be passed as array to other functions or class methods.
$array = typed_array('<int, string>');
$array[1000] = "hello"; // Correct
$array[2000] = 2025; // Error, throws an exception✨ New Features
- Default llHTTP Parser: Starting from v6.1.0, Swoole uses the higher-performance
llhttpas the default HTTP message parser, replacinghttp_parser. - Coroutine-Based File Download:
Swoole\Coroutine\Http\Clientnow supports full coroutine-based file download operations. - Asynchronous File Truncation: Added support for
iouring ftruncate, expanding asynchronous file operation capabilities.
🐛 Bug Fixes
- Thread Mode Optimization:
- Fixed the issue where
hook_flagssettings were ineffective inSWOOLE_THREADmode. - Fixed the issue where heartbeat threads held invalid pointers and accessed freed memory after worker threads restarted due to reaching the
max_requestlimit. - Fixed the issue where
Taskprocesses could not be restarted individually.
- Fixed the issue where
- Stability Improvements:
- Fixed the issue where synchronous processes (including manager and task processes) could not use
process::signal()properly. - Corrected the resource cleanup mechanism when worker processes exit abnormally.
- Resolved compilation failures on the Cygwin platform.
- Fixed the issue where curl could not reuse sockets when keepalive was enabled.
- Improved the logging component to address data consistency issues in multi-threaded mode.
- Fixed compilation failures of the
futexfeature inio_uringonubuntu24.04. - Fixed compilation failures caused by struct sequential assignment on older Linux systems.
- Fixed the issue where the
idproperty of directly instantiatedSwoole\Processobjects was uninitialized. - Fixed the missing
--enable-zstdoption in composer.json when compiling Swoole withPIE.
- Fixed the issue where synchronous processes (including manager and task processes) could not use
- Compatibility Improvements:
- Fixed compatibility issues with
php_swoole_register_shutdown_functionon PHP 8.5. - Corrected the handling of null parameters in
Swoole\Table::get().
- Fixed compatibility issues with
- Protocol Handling:
- Optimized the handling of duplicate fields in HTTP request and response headers to ensure proper merging.
- Fixed the issue where a warning about an unknown compression method was triggered when processing client
Accept-Encoding: zlibheaders withoutzlibinstalled.
Deprecations
- Support for the
selectevent mechanism has been removed.selectonly supports event monitoring for up to1024handles and has significant limitations. On platforms that do not supportepoll/kqueue,pollwill be used as the event polling mechanism, enabling support for high concurrency even on theCygwinplatform. - The second parameter
$waitEventinSwoole\Server::stop()has been deprecated. Please use thereload_asyncparameter instead.
🛠️ Architectural Optimizations
Version 6.1 adds extensive unit tests for core modules, increasing test coverage to 86%. By systematically supplementing test cases and refactoring underlying code logic, combined with full static code analysis using the clang-tidy toolchain, automated code formatting and redundancy cleanup have been achieved, significantly improving code readability and maintainability.
- Optimized the underlying
SSLmodule. - Optimized the underlying
Socketmodule. - Refactored the underlying synchronous signal module.
- Refactored the underlying
reactorandstringmodules. - Refactored the underlying dynamic log file reloading mechanism based on
SIGRTMINsignals. - Optimized the underlying static file server by removing C-style code and unifying it into C++-style code.
- Optimized thread initialization logic to improve multi-threaded performance. Memory for independent management structures is now managed separately, eliminating the need for locks during thread creation and exit.
- Removed the
socket_dontwaitoption from the underlyingasyncmodule, as it is deprecated. - Improved test coverage for
WebSocketmask handling. - Optimized the
sendfilefunctionality to avoid setting thetcp_corkoption for files smaller than64KB. - Added unit tests for
aarch64andmacOSenvironments. - Optimized underlying client network address resolution and settings.
- Added
ssl_cafile/ssl_capathconfiguration items for theServermodule. - Added the
print_backtrace_on_errorconfiguration, which prints C function stack traces when location errors occur. - Added the
Address Sanitizerdebugging tool. - Added
Cygwintesting, significantly improving compatibility and stability on theCygwinplatform. - On
macOSsystems, thekqueueevent mechanism does not support cross-process pipe event monitoring, making it impossible to useSWOOLE_PROCESSmode andTaskprocesses. Therefore, the system defaults to usingpollas the underlying event mechanism. To enablekqueue, manually activate it usingSwoole\Server::set(['enable_kqueue' => true])andswoole_async_set(['enable_kqueue' => true]).
⚠️ Note
- This version is an
RC(Release Candidate) and not an official release. It is recommended for use only in testing environments and should not be used in production.
🙏 Thank You
Sincere thanks to @matyhtf @jingjingxyk @sy-records @KIMDONGYEON00 @ServBayDev @NathanFreeman and all contributors for their professional efforts. Swoole is stronger because of you! Wishing all open-source community partners good health, success in all endeavors, and smooth work.
标准库扩展
6.1 版本 Swoole-Cli 将增加 PHP 标准库扩展语法,在保持对 PHP 官方语法完整兼容的同时,提供一些额外的新语法。这些新的扩展语法均是可选的,不影响现有的PHP代码。标准库扩展语法将在ext-swoole的stdext模块中实现。
swoole-cli用户,可直接使用,无需设置任何额外的参数ext-swoole的用户,需在编译时添加--enable-swoole-stdext来启用stdext在php-cli、php-fpm、cli-http-server、swoole模式均可使用
1. 基础类型对象化
6.1 版本实现了array/string/stream基础类型的对象化封装,支持面向对象风格的方法调用,可直接对这些类型的变量调用内置方法。
基础类型的内置方法实际上仍然是调用PHP标准库实现的,内置方法与PHP的str_或array_系列函数是一一对应关系,例如$text->replace()对应的函数是str_replace。底层仅调整了函数名称,少量方法调整了参数顺序,还有几个方法调整了参数和返回值类型,详情请查看 Swoole 文档。
$text = 'Hello Swoole';
var_dump($text->length());
echo $text->lower()->replace("swoole", "php");
echo fopen("/tmp/test.log")->read(1024);2. Typed-Array 强类型数组
可限制数组类型,如:Map或ArrayList,以及限制key与value的类型。支持多层嵌套格式。typed array实际上依然是array类型,底层仅在写入时进行参数检查。typed array可作为array传递给其他函数或类方法。
$array = typed_array('<int, string>');
$array[1000] = "hello"; // 正确
$array[2000] = 2025; // 错误,抛出异常✨ 新特性
- llHTTP 默认解析器:自 v6.1.0 起,Swoole 采用性能更优的
llhttp替代http_parser作为默认 HTTP 报文解析器。 - 协程化文件下载:
Swoole\Coroutine\Http\Client现支持完整的协程化文件下载操作。 - 异步文件截断:新增
iouring ftruncate支持,扩展异步文件操作能力。
🐛 Bug 修复
- 线程模式优化:
- 修复
SWOOLE_THREAD模式下hook_flags设置失效问题。 - 修复因工作线程达到
max_request限制重启后,导致心跳线程持有失效指针并访问已释放内存的问题。 - 修复不支持单独重启
Task进程的问题。
- 修复
- 稳定性提升:
- 修复同步进程(含 manager 进程和 task 进程)无法正常使用
process::signal()的问题。 - 修正工作进程异常退出时的资源清理机制。
- 解决 Cygwin 平台编译失败问题。
- 修复curl开启keepalive无法复用socket的问题。
- 改进日志组件以解决多线程模式下的数据一致性问题。
- 修复
io_uring的futex特性在ubuntu24.04编译失败的问题。 - 修复结构体顺序赋值在低版本的linux系统会编译失败的问题。
- 修复直接实例化的
Swoole\Process对象其id属性未初始化的问题。
- 修复同步进程(含 manager 进程和 task 进程)无法正常使用
- 修复使用
PIE编译swoole时,composer.json文件缺少--enable-zstd的选项的问题。 - 兼容性改进:
- 修复 PHP 8.5 下
php_swoole_register_shutdown_function兼容性问题。 - 修正
Swoole\Table::get()对 null 参数的处理。
- 修复 PHP 8.5 下
- 协议处理:
- 优化
HTTP请求头与响应头中重复字段的处理机制,确保其正确合并。 - 修复当系统没有
zlib时,处理客户端Accept-Encoding: zlib请求头会触发未知压缩方法警告的问题。
- 优化
废弃
- 不再支持
select事件机制,select仅支持1024个句柄的事件监听,存在严重缺陷,在不支持epoll/kqueue的平台将使用poll作为事件轮训机制,这使得Cygwin平台下也可以支持大量并发。 - 在
Swoole\Server::stop()方法中,第二个参数$waitEvent已被废弃,请使用reload_async参数。
🛠️ 架构优化
6.1版本增加了大量核心模块的单元测试,测试覆盖率提升至**8...
v5.1.8
🐛 Bug Fixes
- Fixed compatibility issues when thread context is enabled with older GCC versions compiling Swoole.
- Fixed CPU affinity support detection failure in newer GCC versions due to missing _GNU_SOURCE macro definition.
- Fixed the issue where synchronous processes (including manager and task processes) couldn't properly use process::signal().
- Fixed missing serverLastStreamId property in HTTP2 coroutine client.
- Fixed the "unknown compression method" warning when system lacks zlib support but client requests zlib in Accept-Encoding header.
- Fixed missing id property in Swoole\Process class.
😊 Thank You
Heartfelt thanks to all contributors @NathanFreeman @xuanyanwow @deminy for your professional dedication. Swoole grows stronger because of you! Wishing our open-source community members good health, success in all endeavors, and smooth work.
🐛 Bug 修复
- 修复 thread context 开启时与低版本 GCC 编译 Swoole 的兼容性问题。
- 修复高版本 GCC 编译时因缺少 _GNU_SOURCE 宏定义导致的 CPU 亲和支持检测失效问题。
- 修复同步进程(含 manager 进程和 task 进程)无法正常使用 process::signal() 的问题。
- 修复 HTTP2 协程客户端缺少 serverLastStreamId 属性的问题。
- 修复系统无 zlib 支持时,客户端请求 Accept-Encoding 含 zlib 会触发未知压缩方法警告的问题。
- 修复 Swoole\Process 类缺少 id 属性的问题。
😊 致谢
诚挚感谢 @NathanFreeman @xuanyanwow @deminy 所有贡献者的专业付出,Swoole 因你们而更强大!愿开源社区伙伴身体健康,万事如意,工作顺利。
v6.0.2
✨ New Features:
- Added
Swoole\Thread::yield(),Swoole\Thread::activeCount(), andSwoole\Thread::isAlive()methods. @matyhtf
🐛 Bug Fixes:
- Fixed an issue where using single-thread mode and setting heartbeat in
SWOOLE_THREADmode would cause exceptions. @matyhtf - Fixed a segmentation fault issue after enabling
swoole.enable_fiber_mock. @NathanFreeman - Fixed an integer overflow issue in the Redis server. @yannaingtun
📢 Note:
- The Redis server currently only supports the
RESP2protocol. When formatting strings that do not comply with this protocol, an exception will be thrown instead of logging. @matyhtf
😊 Thank you:
- Thank you for your contributions to Swoole v6.0.2. Wishing everyone good health, success, and smooth work.
✨ 新特性:
- 增加
Swoole\Thread::yield(),Swoole\Thread::activeCount()和Swoole\Thread::isAlive()方法。 @matyhtf
🐛 Bug修复:
- 修复在
SWOOLE_THREAD模式下,使用单线程模式和设置心跳会引发异常的问题。 @matyhtf - 修复开启
swoole.enable_fiber_mock后的段错误问题。 @NathanFreeman - 修复Redis服务端的整型溢出问题。 @yannaingtun
📢 注意:
- Redis服务端目前将仅支持
RESP2协议,当格式化不符合该协议的字符串时,将抛出异常而不是记录日志。 @matyhtf
😊 致谢:
- 感谢你们为Swoole v6.0.2做出的贡献,祝愿大家身体健康,万事如意,工作顺利。
v5.1.7
🐛 Bug Fixes:
- Fixed an issue where PostgreSQL would revert to synchronous mode under coroutine when receiving large amounts of data. @NathanFreeman
- Fixed an issue where dynamically creating properties in
Swoole\Http2\Requestwould throw an exception. @xuanyanwow @guandeng - Fixed a memory error caused by fatal errors occurring in one-click coroutine. @matyhtf
😊 Thank you:
- Thank you for your contributions to Swoole v5.1.7. Wishing everyone good health, success in all endeavors, and smooth sailing in your work.
🐛 Bug修复:
- 修复Postgresql在协程化下在接收大量数据会退化成同步模式下的问题。 @NathanFreeman
- 修复
Swoole\Http2\Request动态创建类的属性抛出异常的问题。 @xuanyanwow @guandeng - 修复一键协程化中发生的致命错误会导致内存错误的问题。 @matyhtf
😊 致谢:
- 感谢你们为Swoole v5.1.7做出的贡献,祝愿大家身体健康,万事如意,工作顺利。
v6.0.1
🐛 Bug Fixes:
- Fixed an issue in
SWOOLE_THREADmode where the process could not exit properly due to not removing the listening event. @NathanFreeman - Fixed an issue where large file uploads failed when the
single_threadconfiguration was enabled. @matyhtf - Fixed an issue where compilation could not find the specific file path if the same variable was already defined in
config.m4. @matyhtf - Fixed an issue in
Swoole\Process\Poolwhere processes could not exit properly upon timeout. @matyhtf - Fixed an issue in
SWOOLE_THREADmode where callingputenvcaused the program to crash. @matyhtf - Fixed an issue in
SWOOLE_THREADmode where event callback functions could not be set for independent ports. @matyhtf - Fixed an issue in
SWOOLE_THREADmode where runtime parameters could not be retrieved in events such asonWorkerStart. @matyhtf - Fixed an issue where Postgresql would degrade to synchronous mode when receiving large amounts of data under coroutine. @NathanFreeman
- Optimized the parameter judgment logic of
swoole_substr_json_decode/swoole_substr_unserializefunctions. @Appla - Fixed an issue with CPU affinity settings in
config.m4. @remicollet - Fixed an issue in
SWOOLE_THREADmode where the heartbeat detection did not function properly. @matyhtf
📢 Note:
- In the Http service, if the process restarts, the underlying layer will send a 500 Internal Server to requests waiting in the queue, close the connection, and discard these requests after sending. @NathanFreeman
- Since the runtime configuration relied upon by the
stream factoryandstream opsin the PHP underlying is not thread-safe, in multi-thread mode, only the main thread is allowed to modify these runtime configurations before creating child threads. @matyhtf - Upgrade nghttp2 to the latest version. @NathanFreeman
😊 Thank you:
- Thank you for your contribution to
Swoole v6.0.1. Wish you good health, all the best, and smooth work.
🐛 Bug修复:
- 修复
SWOOLE_THREAD模式下,因为没有移除监听事件导致进程无法正常退出的问题。 @NathanFreeman - 修复当开启
single_thread配置时,无法上传大文件的问题。 @matyhtf - 修复如果已经定义了
config.m4中相同的变量,会导致编译过程找不到具体的文件路径的问题。 @matyhtf - 修复
Swoole\Process\Pool中进程超时无法正常退出的问题。 @matyhtf - 修复
SWOOLE_THREAD模式下,调用putenv导致程序崩溃的问题。 @matyhtf - 修复
SWOOLE_THREAD模式下,无法为独立的端口设置事件回调函数的问题。 @matyhtf - 修复
SWOOLE_THREAD模式下,onWorkerStart等事件中无法获取到运行时的各项参数的问题。 @matyhtf - 修复Postgresql在协程化下在接收大量数据会退化成同步模式下的问题。 @NathanFreeman
- 优化
swoole_substr_json_decode/swoole_substr_unserialize函数的参数判断逻辑。 @Appla - 修复
config.m4中的CPU亲和性设置的问题。 @remicollet - 修复
SWOOLE_THREAD模式下,心跳检测不起作用的问题。 @matyhtf
📢 注意:
- 在Http服务中,如果进程重启时,底层会发送500 Internal Server给队列中等待处理的请求,发送完毕就关闭连接并丢弃这些请求。 @NathanFreeman
- 由于php底层的
stream factory和stream ops依赖的运行时配置不是线程安全的,因此多线程模式下只允许主线程在还没创建子线程之前修改这些运行时配置。 @matyhtf - 升级nghttp2到最新版本。 @NathanFreeman
😊 致谢:
- 感谢你们为
Swoole v6.0.1做出的贡献,祝愿大家身体健康,万事如意,工作顺利。