立即处理可能影响正在运行的系统
隧道与证书锁修复在 build 16672 稳定
本批次修复了隧道中继、证书链、时区查找和 POSIX 线程池关闭中的死锁与竞争。公共扩展点 TWebSocketProtocol.SetSubprotocol 也被替换,因此自定义 WebSocket 协议子类需要修改源码。隧道和 Zstandard 用户应采用最终 build,而不是中间修订。
要点
- 应落在 2.4.16672:隧道同步一直调整到最终提交,中间还包含 BSD 与 Delphi 的后续修复。
- 自定义 TWebSocketProtocol 子类必须将 SetSubprotocol 重写改为 IsSubprotocol,并在需要初始化时重写 SetName。
- TEccCertificateChain.ValidateItems 不再自行加锁;调用方必须串行化,而 SaveToBinary 现在使用写锁。
- POSIX TSynThreadPool 现在使用 O(1) 环形队列,并在关闭时安全拒绝或中止上下文。
- 并发 TAlgoZstd 调用会创建临时上下文,不再阻塞于单个共享上下文;该单元仍明确标记为未完成。
升级建议
隧道、POSIX 线程池、ECC 证书链或 Zstandard 工作负载应使用 build 2.4.16672,不要停在隧道修复序列的中间版本。重新构建前,请在自定义 WebSocket 协议类中搜索 SetSubprotocol,并检查证书流程中的并发 ValidateItems 调用。
20 条中的 20 条 · 上游 20 次提交
1
高
隧道回调在中继锁和会话锁之外释放
在 mormot.net.tunnel 中,TTunnelList 现在继承 TSynPersistent,并拥有专用的 TRWLightLock fSessionSafe。新增的 Extract 在保留本地引用的同时移除 ITunnelTransmit;Delete 与 TTunnelRelay.ConsoleDelete 离开锁后再释放该引用。ConsoleTunnelSend 也在 fConsoleSafe 之外调用远程回调。
破坏性变更
mormot.net.tunnel
aef05e96+70-41
net: some Tunnel logic fixes
影响
隧道关闭与帧传递不再在持有共享中继锁时执行接口终结器或远程代码,从而降低死锁和重入风险。继承 TTunnelList 或访问其继承属性 Safe 的代码会因基类变化而无法编译。
值得一看
采用 build 2.4.16672,并在重新构建隧道服务前搜索 TTunnelList 子类和 .Safe 访问。
公开 API
TTunnelListsignature-changed — 其基类从 TObjectRWLightLock 改为 TSynPersistent;继承的 Safe 接口随之消失。TTunnelList.Extractadded — 移除会话并返回其 ITunnelTransmit,以便在锁外释放。
2
高
WebSocket 子协议匹配拆分识别与实例初始化
TWebSocketProtocol.SetSubprotocol 被移除。新的公共虚方法 IsSubprotocol 只执行只读识别,受保护虚方法 SetName 则通过 Name 属性配置克隆或选中的实例。二进制、relay、client 与 Engine.IO 协议均采用该拆分,匹配时不再修改共享原型。
破坏性变更
mormot.net.relay+2
17f74f81+31-25
net: new TWebSocketProtocol.IsSubprotocol/SetName methods
影响
子协议协商变得线程安全,因为匹配不再修改共享协议对象。任何重写或调用 SetSubprotocol 的自定义子类都会编译失败,必须将识别与实例配置分开。
需要迁移
将 SetSubprotocol 重写替换为 IsSubprotocol;若所选协议名需要配置克隆实例,请把状态修改移入 SetName。
公开 API
TWebSocketProtocol.SetSubprotocolremoved — 由 IsSubprotocol 负责匹配,SetName 负责实例配置。TWebSocketProtocol.IsSubprotocoladded — 公共虚拟只读子协议识别方法。TWebSocketProtocol.Namebehaviour-changed — 写入 Name 现在调用虚方法 SetName,可执行实例级配置。
3
高
证书链验证避免死锁,但需由调用方串行化
TEccCertificateChain.ValidateItems 移除外围 fSafe.ReadLock,因为内部每次 IsValid 调用都会自行获取证书链锁,可能导致死锁。公共文档现明确说明 ValidateItems 非线程安全,应在加载后执行。
破坏性变更
mormot.crypt.ecc
fbb6f6dc+7-10
crypt: fixed potential deadlock in TEccCertificateChain.ValidateItems
影响
验证不再自锁,但并发修改或另一个 ValidateItems 调用可能与未保护的 fItems 遍历发生竞争。同时执行证书链重载与验证的后端必须在外部串行化此方法。
需要迁移
搜索 ValidateItems,确保其不会与证书链加载、吊销更新或另一次验证调用重叠。
公开 API
TEccCertificateChain.ValidateItemsbehaviour-changed — 该方法现在明确非线程安全,需要调用方串行化。
4
高
POSIX 线程池关闭消除入队竞争
TSynThreadPool 将 POSIX 队列锁改名为 fPendingSafe,并在持锁时设置 fTerminated。Enqueue 在同一锁下检查终止状态,worker 在停止时中止已取得的上下文,DoTaskAbort 则保证 TaskAbort 的异常安全。TSynParallelProcess 也明确执行 BSD 所需的 TOSLightLock 初始化。
修复
mormot.core.threads
76f15a86+60-44
core: another pass on TSynThreadPool shuhtdown logic
影响
生产者无法再向已进入销毁流程的线程池入队,待处理上下文也更不易泄漏或阻塞关闭。此变化影响基于 TSynThreadPool 的 POSIX 服务器;Windows IOCP 仍走独立路径。
建议升级
升级会销毁活动线程池的 POSIX 服务,并在负载下测试关闭。
5
高
隧道列表不再在读锁内调用远程代码
TTunnelList 新增 Get,在读锁下复制 ITunnelTransmit。TunnelSend、GetInfo 与 GetAllInfo 随后在解锁后调用接口方法;GetAllInfo 同时快照接口和会话 ID。DeleteFrom 拒绝对自身删除,后续提交还继续完善该流程。
修复
mormot.net.tunnel
4be92b7a+44-39
net: fixed race/deadlock in TTunnelList
影响
回调重入列表或释放其他接口时,不再会死锁列表的读写锁。由于该区域一直变化到 build 16672,应仅在最终修订上测试中继创建、帧传递和关闭。
值得一看
仅将此修复作为以 build 16672 结束的完整序列的一部分,并运行并发隧道生命周期测试。
公开 API
TTunnelList.Getadded — 返回会话对应的线程安全本地 ITunnelTransmit 引用。
6
高
后续提交修复三处锁初始化与嵌套缺陷
TAlgoZstd 现在在持有对应锁时延迟创建共享压缩与解压上下文。THttpPeerCrypt 为 BSD 明确初始化和结束新的 TOSLightLock。TTunnelList.DeleteFrom 在源读锁下复制会话 ID,解锁后再删除,避免嵌套列表锁。
修复
mormot.lib.zstd+2
0a0f36a4+23-13
all: fixes several locking issues
影响
此提交修复同批次较早引入的回归:Zstandard 上下文过早创建、BSD 对等客户端锁未初始化,以及隧道列表锁可能形成循环。对于这些组件,build 16660-16667 不适合作为落点。
建议升级
跳过受影响的中间 build,Zstandard、peer-cache 或隧道部署应使用 2.4.16672。
7
高
时区查找保护共享的最近结果缓存
TSynTimeZone 新增专门保护 fLastZone 与 fLastIndex 的 TLightLock fLastZoneSafe。LockedSearch 在新锁下读取和更新缓存,哈希时区查找仍由现有外围读锁保护。
修复
mormot.core.search
55fa224e+17-12
core: fixed TSynTimeZone.LockedSearch thread safety
影响
使用不同时区 ID 的并发转换不再竞争共享的最近时区文本和索引,避免返回不匹配的缓存索引。使用 TSynTimeZone.Default 的多线程 REST 后端应采用此修复。
建议升级
升级执行并发 TSynTimeZone 转换的服务,并重新运行跨时区日期测试。
8
高
Delphi 构建适配演进中的隧道类型
mormot.net.tunnel 新增公共动态数组别名 ITunnelTransmits,用于 TTunnelList 存储和本地副本;Get 的接口参数改为 out;FrameSession 中不可内联的 TRAIL_SIZE 引用改为 SizeOf(TTunnelSession)。
编译器与平台
mormot.net.tunnel
804bc970+6-5
net: fixed Delphi compilation
影响
前一个隧道修订无法使用 Delphi 编译。此提交恢复 Delphi 兼容性,但隧道逻辑在 build 16672 中再次变化,因此应采用本期头部版本。
建议升级
不要停在 build 16668;请使用 build 16672 编译 Delphi 隧道项目。
公开 API
ITunnelTransmitsadded — array of ITunnelTransmit 的公共别名。TTunnelList.Getsignature-changed — ITunnelTransmit 输出参数从 var 改为 out。
9
高
BSD 隧道线程现会初始化操作系统锁
TTunnelLocalThread.Create 调用 fSafe.Init,析构函数调用 fSafe.Done。在 BSD 上,TOSLightLock 映射为 TRtlCriticalSection,不能只依赖类存储的零初始化。ORM 差异仅说明 TOrmPropertiesAbstract.fSafe 已遵守的同一要求。
编译器与平台
mormot.net.tunnel+1
428ee221+6-4
net: fixed TTunnelLocalThread.Create on BSD
影响
否则 BSD 隧道创建可能操作未初始化的临界区。后续提交仍继续修改隧道代码,因此应通过 build 16672 获取此修复。
10
中
证书二进制导出现排除并发写入
TEccCertificateChain.SaveToBinary 将 fSafe.ReadLock 改为 fSafe.WriteLock,因为序列化会在 SaveToStream 前后临时切换每个 TEccCertificate.fStoreOnlyPublicKey 标志。
修复
mormot.crypt.ecc
6c82cf93+4-4
crypt: fixed TEccCertificateChain.SaveToBinary thread safety
影响
并行 SaveToBinary 调用不再竞争临时证书标志,避免产生不一致的私钥/公钥序列化。更强的锁可能串行化少见的并发导出,但不会改变二进制格式。
建议升级
升级从多个线程导出同一 TEccCertificateChain 的后端。
公开 API
TEccCertificateChain.SaveToBinarybehaviour-changed — 序列化期间现在获取证书链写锁。
11
中
Zstandard 调用不再排队等待单一共享上下文
TAlgoZstd 预分配共享压缩与解压上下文,并为每次操作尝试 TryLock。竞争线程会创建并释放临时 ZSTD_CCtx 或 ZSTD_DCtx,而不是等待共享上下文。
性能
mormot.lib.zstd
83c4df20+44-36
lib: fixed TAlgoZstd context usage
影响
并行 Zstandard 操作可并发执行,不再形成单一锁队列。该单元仍标记为未完成且仅限 FPC,build 16668 又将共享上下文改为延迟创建,因此此提交不适合作为独立落点。
值得一看
若启用 mormot.lib.zstd,仅在 build 16668 或更高版本上进行基准与压力测试;优先使用本期头部。
12
中
POSIX 待处理任务实现常数时间出队
POSIX TSynThreadPool 待处理数组改为由 fPendingFirst 与 fPendingLast 跟踪的固定环形 FIFO。PopPendingContext 只推进索引,不再移动所有剩余指针;队列按 QueueLength 一次性分配。
性能
mormot.core.threads
6f064610+43-30
core: ensure TSynThreadPool POSIX queue is O(1)
影响
出队成本不再随积压量增长,可缩短突发流量下内部锁的持有时间。该变化仅限 POSIX,不改变 TSynThreadPool 公共 API。
13
中
隧道 accept 等待在竞争时不再持续消耗 CPU
TTunnelLocalThread.fSafe 从 TLightLock 改为 TOSLightLock。当后台线程阻塞在 accept 时,OnReceived 可通过 Linux 或现代 Windows 的 futex 路径等待。
性能
mormot.net.tunnel
75bf7660+4-4
net: optimized TTunnelLocalThread accept() step
影响
早到的隧道帧等待本地套接字被接受时不再占用 CPU 自旋。此变化需要下一个 build 中的 BSD 初始化修复。
14
中
Peer-cache 客户端竞争改用操作系统辅助锁
THttpPeerCrypt.fClientSafe 从 TLightLock 改为 TOSLightLock,使竞争等待使用平台的 futex 类实现,而不是纯自旋。
性能
mormot.net.server
a5e68484+3-3
net: refined THttpPeerCrypt HTTP client lock
影响
多个线程争用共享 HTTP 客户端时,后台直连下载应减少 CPU 消耗。此修订缺少 build 16668 增加的 BSD 显式 Init 与 Done 调用。
15
低
POSIX 线程池协调恢复短时自旋锁
内部 POSIX TSynThreadPool.fSafe 从 TOSLightLock 改为四字节 TLightLock,并移除相关 Init 与 Done 调用。受保护的临界区只分配指针和队列元数据。
性能
mormot.core.threads
844e8029+5-8
core: refined TSynThreadPool internal POSIX lock
影响
极短的 POSIX 线程池操作可避免操作系统辅助锁开销。队列与关闭逻辑在 build 16670 和 16671 中再次调整,因此此版本不应单独作为落点。
16
低
SQL 代理事务锁改用更轻量的操作系统原语
TSqlDBProxyConnectionProtocol.fSafe 从 TOSLock 改为 TOSLightLock,在 Linux 和 Windows 8 及更高版本上对应更轻量的 futex 支持互斥量。事务算法与公共方法均未改变。
性能
mormot.db.proxy
907c92f5+3-3
db: refined TSqlDBProxyConnectionProtocol lock
影响
远程 SQL 代理事务在轻度竞争下可能降低锁开销。应用代码无需迁移,行为也不变。
17
低
锁清理保持运行时行为不变
mormot.core.os、mormot.net.async、mormot.rest.http.server 与 mormot.soa.server 中的注释和锁作用域得到澄清。异步 TLS 路径在持有 fGC1.Safe 时再次检查 Enabled,SOA 会话查找在返回前释放读锁。
内部重构
mormot.core.os+3
ccde07c6+8-7
core: some code refactoring with no functional change
影响
公共 API 与预期应用行为均不变。双重检查可防止多个连接同时进入初始化时重复配置 TLS。
18
低
多线程测试框架覆盖所有轻量锁系列
新增的 test.core.threads 单元增加 1,166 行压力测试,覆盖多个 worker 线程下的 TLightLock、TOSLightLock、TOSRWLightLock、TRWLightLock 及相关锁行为。
测试
719cd877+1168-2
tests: extended T*Lock coverage
影响
应用代码不变。该套件提高了对近期锁重写的信心,但本身不能证明所有更高层隧道或关闭流程都无竞争。
19
低
LDAP 测试覆盖自定义组成员属性
TNetworkProtocols 为自定义 LDAP 组成员解析增加断言,包括规范化的 distinguished name 与配置的 member 属性路径。仅修改 test/test.net.proto.pas。
测试
4e783875+8-4
tests: cover LDAP custom members parsing
影响
应用与框架运行时均无变化。这些测试保护上一期引入的 LDAP 自定义成员行为。
20
低
主测试程序现会运行新的锁测试套件
test/mormot2tests.dpr 将 test.core.threads 加入 uses 列表,使新锁测试成为常规 mormot2tests 可执行程序的一部分。
测试
62bd0e82+5-2
tests: include test.core.threads in mormot2tests project
影响
对运行时和应用代码没有影响。持续测试现在会执行前一提交新增的锁测试框架。