立即处理可能影响正在运行的系统
锁与进程修复使 build 16652 成为安全落点
这一批次修复了两个生产风险:TOSLightLock 中可能丢失唤醒的竞态,以及 POSIX RunRedirect 中长期存在的多个问题,包括孤儿子进程和 EOF 忙循环。同时还新增了基于 futex 的读写锁,修正了 ODBC 类型推断,扩展了 LDAP 与堆栈跟踪 API,并在最终 build 前解决了 Delphi 和 BSD 编译回归。
要点
- TOSLightLock.UnLock now uses a mandatory CAS, preventing a waiter from being forgotten during unlock.
- POSIX RunRedirect no longer leaks child process groups or spins at 100% CPU after EOF, and now honors environment and working-directory arguments.
- ODBC column binding now uses the real precision and maps SQL_FLOAT separately from DECIMAL and NUMERIC.
- New public APIs include TOSRWLightLock, TDebugFile.StackTrace, LDAP formatting and DN filtering helpers, and TAsnObjects.
- Land on build 2.4.16652; earlier snapshots in this batch contain Delphi, BSD, or WaitForSafe source-compatibility regressions.
升级建议
对于使用 RunRedirect 的 POSIX 服务、使用 TOSLightLock 的负载、ODBC 使用者或任何 Delphi/BSD 构建,应拉取最终的 2.4.16652 修订。不要停在中间修订,因为本批后续提交修复了同一序列早期引入的编译与源码兼容性问题。
21 条中的 21 条 · 上游 23 次提交
1
高
POSIX RunRedirect 不再泄漏子进程或在 EOF 后忙循环
FPC POSIX 实现用预先准备的 fork/execve 路径替代 popen。子进程创建独立会话,stdout 显式进入管道,超时会向整个进程组发信号,EOF 判断改为 n<=0,环境和工作目录参数得到遵守,简单命令使用所提供环境中的 PATH,未中止时 exitcode 接收 WaitProcess 结果。
修复
mormot.core.os.posix
667509df+231-77
core: rewrite POSIX RunRedirect() from popen() to fork/execve - fix #463
影响
当子进程关闭 stdout 时,INFINITE 等待不再进入 100% CPU 循环;中止不再把 shell 启动的 worker 作为 PID 1 下的孤儿;wrkdir 不再改变父进程;POSIX 的 env/options 不再被静默忽略。公共签名不变,但执行语义得到实质修正。
建议升级
升级使用 RunRedirect 的 POSIX 服务,并测试正常退出、EOF、超时、回调中止、自定义 env/PATH、工作目录和后代进程终止。
公开 API
RunRedirectbehaviour-changed — POSIX 执行现在使用 fork/execve,遵守现有参数,返回实际退出码并终止进程组。
2
高
TOSLightLock 解锁时可能遗漏等待线程
TOSLightLock.UnLock 现在始终先通过 LockedExc32 将 EV_LOCKED 改为 EV_NONE,再选择唤醒路径。旧的 Intel 快速路径先读取 fMutex,再非原子地写入 EV_NONE,等待线程可能在两者之间发布 EV_WAITER 并被覆盖。
修复
mormot.core.os
ad8f8d38+6-16
core: fixed race in TOSLightLock.UnLock
影响
在争用下,旧解锁序列可能忘记唤醒等待线程,使其无限期阻塞。直接或通过框架内部使用 TOSLightLock 的服务应采用此修复,尽管无争用时会增加少量 CAS 成本。
建议升级
使用 build 2.4.16652 或更高版本重新构建高并发服务,并重新运行锁争用测试。
公开 API
TOSLightLock.UnLockbehaviour-changed — 解锁现在先执行原子状态转换,再决定是否需要唤醒等待线程。
3
高
新锁与 LDAP API 的 Delphi 编译已恢复
TOSRWLightLock 移除了 Delphi 无法内联的方法上的 inline 指令。在 mormot.net.ldap 中,匿名集合声明改为 TNormalizeDN 枚举和 TNormalizeDNs 集合,DNToCN、DNsToCN 与 NormalizeDN 改为接收 TNormalizeDNs。
编译器与平台
mormot.core.os+1
63b43ba0+12-12
net: fixed Delphi compilation
影响
Delphi 现在可以编译本批早先引入的 API。针对临时 build 16630 编写的代码必须把集合类型 TNormalizeDN 变量替换为 TNormalizeDNs;使用最终 API 的代码无需迁移。
建议升级
跳过中间构建,使用 build 2.4.16652 编译 Delphi 应用;若已采用 build 16630,请搜索 TNormalizeDN。
公开 API
TNormalizeDNsadded — 用于 DN 过滤的集合类型现在明确命名为 TNormalizeDNs。DNToCN / DNsToCN / NormalizeDNsignature-changed — 其 extend 参数使用 TNormalizeDNs,而不是临时的集合类型 TNormalizeDN。
4
高
最终修订恢复 BSD 构建和 WaitForSafe 默认参数
在 mormot.core.os 中,SPIN_FUTEX 被移出仅限 OSFUTEX 的代码块,使 BSD 上的 TOSRWLightLock 回退代码可以引用它。TSynEvent.WaitForSafe 也恢复了公共默认参数 DisableSafe=false。
编译器与平台
mormot.core.os
951b4afd+6-5
core: fixed BSD compilation
影响
BSD 目标现在可以编译新的读写锁,仅以超时参数调用 WaitForSafe 的现有源码也能再次编译。应使用此修订,而不是中间的 16645-16651 构建。
建议升级
在编译 BSD 目标或采用本期其他更改前,应落在此修订。
公开 API
TSynEvent.WaitForSafesignature-changed — DisableSafe 在 build 16645 中一度成为必填参数,现在再次默认为 false。
5
中
ODBC 绑定现在遵守声明的数值精度
TSqlDBOdbcStatement.BindColumns 现在把 SQLDescribeColW 返回的真实 ColumnSize 和 DecimalDigits 传给 ODBCColumnToFieldType,而不是使用硬编码精度 10。SQL_FLOAT 也不再进入 DECIMAL/NUMERIC 的整数与货币启发式,而是直接映射为 ftDouble。
修复
mormot.db.sql.odbc
5c4a0328+7-7
db: fixed TSqlDBOdbcStatement.BindColumns
影响
ODBC 结果列现在可能返回正确的 ftInt64、ftCurrency 或 ftDouble,而不是根据精度 10 推断的类型。依赖旧错误元数据或转换行为的应用应进行回归测试。
建议升级
通过生产中使用的每个 ODBC 驱动重新测试 DECIMAL、NUMERIC 和 FLOAT 结果列。
6
中
WaitForSafe 优先处理主线程同步工作
在主线程中,TSynEvent.WaitForSafe 现在调用 CheckSynchronize(10),随后用 WaitFor(0) 轮询事件;此前是同步检查 1 毫秒并在事件上阻塞 10 毫秒。零超时会绕过安全循环。
修复
mormot.core.os
46404091+6-5
core: fixe TSynEvent.WaitForSafe Synchronize() call
影响
主线程等待会更及时地处理排队的 Synchronize 调用,并在不增加阻塞间隔的情况下检查事件。对同步顺序或超时边界敏感的代码应重新测试。
值得一看
重新测试依赖精确超时或 Synchronize 顺序的主线程 RunWait 或直接 WaitForSafe 用法。
公开 API
TSynEvent.WaitForSafebehaviour-changed — 安全的主线程等待现在优先执行 CheckSynchronize,并使用非阻塞事件检查。
7
中
无需抛出异常即可捕获堆栈跟踪
TDebugFile 新增 StackTrace 重载,可返回 RawUtf8 或追加到 TTextWriter,并支持 skip、depth 与 TSynLogStackTraceUse 控制。FPC 使用 CaptureBacktrace,Delphi Windows 使用 RtlCaptureStackBackTrace,并在 Win32 上手动回退;TSynLog 共享该实现。
新功能
mormot.core.log
702c8d0c+208-47
core: add TDebugFile.StackTrace() methods - request #401
影响
诊断端点和错误报告可在不构造异常的情况下捕获当前线程堆栈。在 FPC x86_64 上,有效帧仍依赖栈帧生成;Delphi POSIX 当前不会追加内容。
公开 API
TDebugFile.StackTraceadded — 两个重载可在无异常情况下以文本形式捕获当前线程堆栈。
8
中
新增由操作系统辅助且读者优先的读写锁
mormot.core.os 新增 TOSRWLightLock:一个 32 位读者计数器与写入标志,在 Windows 8+ 使用 WaitOnAddress/WakeByAddress,在 Linux 使用 futex,其他平台使用自旋回退。它公开 Init、Done、读写锁、尝试锁、解锁和 IsLocked 方法。
新功能
mormot.core.os
583fe89c+196-7
core: new TOSRWLightLock efficient object
影响
应用获得了相对于写者优先 TRWLightLock 的低开销读者优先替代方案。持续读者可能延迟写者,并且在读锁或写锁内部再次申请写锁按契约仍会死锁。
值得一看
仅在可接受读者优先时使用 TOSRWLightLock;若排队写者必须阻止新读者,请保留 TRWLightLock。
公开 API
TOSRWLightLockadded — 新增读者优先、由操作系统辅助的读写锁 record/object。
9
中
LDAP DN 转换可选择 CN、OU 和 DC 组件
DNToCN、DNsToCN 和 NormalizeDN 新增可选 extend 集合,用于控制结果中是否包含 CN、OU 与 DC。默认值保留原有全部组件输出;build 16639 随后将该集合最终命名为 TNormalizeDNs。
新功能
mormot.net.ldap
9411aea0+52-24
net: introducing TNormalizeDN extend e.g. for DNToCN()
影响
LDAP 应用可生成仅包含所选 DN 层级的规范名或标准化名称,无需再次解析字符串。由于 DN_ALL 仍为默认值,现有调用输出不变。
公开 API
DNToCN / DNsToCN / NormalizeDNsignature-changed — 新增可选组件选择参数,默认值为 DN_ALL。
10
中
跨平台 futex 层现在可唤醒所有等待线程
新增 OsWakeAllOnValue 回调:在 Windows 8+ 映射到 WakeByAddressAll,在 Linux 映射到带 MaxInt 的 FUTEX_WAKE_PRIVATE。它补充了 OsWaitOnValue 和单等待者 OsWakeOnValue。
新功能
mormot.core.os+2
c849d860+25-12
core: implemented WakeByAddressAll() on Win8+ and Linux
影响
TOSRWLightLock 等框架原语可在写者释放锁后唤醒所有读者。除非代码直接选择新回调,否则现有应用行为不变。
公开 API
OsWakeAllOnValueadded — 新增可选回调,用于唤醒等待某个 32 位值的所有线程。
11
中
TLoggedWorker 改为等待事件而非轮询
TLoggedWorker 现在拥有名为 fIdle 的 TSynEvent。RunOne 在工作开始时重置它,RunDone 在 fRunning 归零时发出信号,RunWait 将超时和可选主线程同步委托给 WaitForSafe。
性能
mormot.core.threads
a22faf70+31-20
core: let TLoggedWorker use TSynEvent for WaitFor()
影响
等待不再每 10 毫秒唤醒,降低了空闲 CPU 使用,并在 worker 变为空闲时立即响应。契约现在明确只允许一个并发 RunWait 调用者。
值得一看
检查应用代码是否会在同一 TLoggedWorker 实例上并发调用 RunWait。
公开 API
TLoggedWorker.RunWaitbehaviour-changed — 实现改为事件驱动,并且一次仅支持一个等待线程。
12
低
LDAP 属性列表新增格式化值插入
TLdapAttributeList.AddFmt 使用 FormatUtf8 格式化 RawUtf8 值,然后以指定 TLdapAddOption 转发给现有 Add 重载,并返回受影响的 TLdapAttribute。
新功能
mormot.net.ldap
c7ba1bb3+17-3
net: new TLdapAttributeList.AddFmt() method
影响
LDAP 客户端代码可在无需临时字符串的情况下构建格式化属性值。现有 Add 调用和行为不变。
公开 API
TLdapAttributeList.AddFmtadded — 新增类似重载的格式化值辅助方法,使用 FormatUtf8 参数。
13
低
ASN.1 对象新增类型化动态数组辅助项
mormot.core.os.security 新增 TAsnObjects(TAsnObject 数组)和 AsnAddItem,用于追加一个编码对象并返回其零基索引。声明的用例是构建 LDAP 修改项。
新功能
mormot.core.os.security
446a5be1+15-2
core: new TAsnObjects type and its AsnAddItem() wrapper
影响
组装多个 ASN.1 值的代码可使用命名数组类型并避免重复 SetLength 样板。现有 ASN.1 编码 API 不变。
公开 API
TAsnObjectsadded — 用于多个 TAsnObject 值的动态数组类型。AsnAddItemadded — 追加 ASN.1 对象并返回其索引。
14
低
Windows 套接字轮询启用待处理事件快速路径
TPollSockets.PollForPendingEvents 不再将 fPendingSafe.TryLock 快速路径限制于 POSIX。Windows 现在也尝试相同的非阻塞锁,并在无争用时直接移动待处理事件。
性能
mormot.core.os+1
79dd6c23+2-5
core: some TPollSockets optimization on Windows
影响
频繁变更套接字订阅的 Windows 服务器可能减少合并待处理事件的时间。此更改为内部实现,应用代码无需修改。
15
低
待处理套接字事件改用低争用下成本更低的锁
TPollSockets.fPendingSafe 从 TOSLightLock 改为 TLightLock。提交说明待处理事件的争用很小,而 TOSLightLock.UnLock 新增的强制 CAS 使简单锁在此处更快。
性能
mormot.net.sock
60cb8bc7+3-3
net: let TPollSockets use TLightLock for the Pending envents
影响
套接字轮询保留竞态修复,同时避免此内部队列在无争用解锁时的额外成本。应用代码无需修改。
16
低
TRWLightLock 新增空终结方法以便锁互换
TRWLightLock 现在公开空方法 Done,与 TOSLock 及相关原语的生命周期形式一致。文档也明确说明写者优先。
编译器与平台
mormot.core.os
d5844b6a+12-2
core: new TRWLightLock.Done void method
影响
通用代码可对任一锁类型调用 Init 和 Done,无需条件清理。Done 不执行任何操作,因此现有运行时行为不变。
公开 API
TRWLightLock.Doneadded — 与其他锁 record 兼容的空生命周期方法。
17
低
数据库和 REST 类注册表改用指针数组
TSqlDBConnectionProperties 和 TRest 的内部类定义注册表现在调用 PtrArrayAddOnce,不再通过 TObject 转换存储 TClass。ODBC 辅助函数的名称和格式也被规范化,但作用域未变。
内部重构
mormot.db.sql+2
9fbd6c32+13-13
all: minor code refactoring
影响
没有功能变化,也无需迁移应用。注册表表示现在与实际存储的指针值一致。
18
低
隧道中继测试移除未使用的随机生成器变量
TNetworkProtocols.TunnelRelay 不再声明和初始化未使用的 PLecuyer 变量。测试断言、控制流和框架单元均未改变。
测试
b1f1302d+2-4
tests: minor unused variable cleanup
影响
对应用代码或运行时行为没有影响;此更改仅消除测试套件中的编译器警告。
19
低
文本单元断言格式化器仍可容纳于栈缓冲区
mormot.core.text 初始化新增 Assert,确认 SizeOf(TFormatUtf8) 不超过 SizeOf(TTextWriterStackBuffer)。当前预期大小分别为 4 KB 和 8 KB。
测试
mormot.core.text
e171e5aa+3-2
core: added paranoid Assert() about TFormatUtf8
影响
正常构建没有行为变化。启用断言的构建会在未来格式化器增长破坏栈缓冲假设时尽早失败。
20
低
锁偏好和待处理套接字行为得到说明
注释现在区分 TOSRWLightLock 的读者优先策略与 Windows SRW 锁定模式,并更准确地说明 TPollSockets 的待处理事件重写。EnsurePending 也显式命名起始索引,但搜索逻辑未变。
文档
mormot.core.os+1
181c2d7b+13-9
core: mostly comments/documentation precisions
影响
对运行时和源码没有影响。文档更清楚地说明了锁选择权衡和套接字子类职责。