🔴 [H1] mmap SIGBUS handler 并发安装会写 static mut 导致 UB #33

Closed
opened 2026-06-05 11:53:22 +08:00 by dailz · 1 comment
Owner

问题

crates/bench/src/mmap_reader.rsinstall_sigbus_handler() 每次 mmap reader open 时都会无条件执行,并写入 static mut OLD_SIGBUS_HANDLERcrates/bench/src/suites/concurrent.rs 的并发 benchmark 会让多个线程同时调用 B::open(),产生无同步全局写入。

影响

  • 多线程写 static mut OLD_SIGBUS_HANDLER 属于 Rust 未定义行为。
  • 后续安装可能把 old handler 保存为自定义 sigbus_handler 自身;若 handler 内 mmap(MAP_FIXED) 失败,fallback 链式调用会递归调用自身。

位置

  • crates/bench/src/mmap_reader.rs:26
  • crates/bench/src/mmap_reader.rs:82
  • crates/bench/src/suites/concurrent.rs:68

建议

OnceLock<Option<SigHandler>>Once 确保 SIGBUS handler 全局只安装一次;优先移除 static mut,在 handler 中通过同步初始化后的只读状态读取 old handler。

## 问题 `crates/bench/src/mmap_reader.rs` 中 `install_sigbus_handler()` 每次 mmap reader open 时都会无条件执行,并写入 `static mut OLD_SIGBUS_HANDLER`。`crates/bench/src/suites/concurrent.rs` 的并发 benchmark 会让多个线程同时调用 `B::open()`,产生无同步全局写入。 ## 影响 - 多线程写 `static mut OLD_SIGBUS_HANDLER` 属于 Rust 未定义行为。 - 后续安装可能把 old handler 保存为自定义 `sigbus_handler` 自身;若 handler 内 `mmap(MAP_FIXED)` 失败,fallback 链式调用会递归调用自身。 ## 位置 - `crates/bench/src/mmap_reader.rs:26` - `crates/bench/src/mmap_reader.rs:82` - `crates/bench/src/suites/concurrent.rs:68` ## 建议 用 `OnceLock<Option<SigHandler>>` 或 `Once` 确保 SIGBUS handler 全局只安装一次;优先移除 `static mut`,在 handler 中通过同步初始化后的只读状态读取 old handler。
dailz closed this issue 2026-06-05 13:22:10 +08:00
Author
Owner

修复方案

经 Oracle 审核后采用 Once + 原始原子变量 方案,消除 static mut UB。

核心改动 (crates/bench/src/mmap_reader.rs)

改动 说明
static mut OLD_SIGBUS_HANDLERAtomicU8 + AtomicPtr 消除并发写入 UB
install_sigbus_handler()Once::call_once 保证多线程只安装一次
查询 → 发布原子 → 安装 handler 消除 handler-active-but-state-unpublished 竞态窗口
si_addr 页对齐 & !0xFFF 防止 mmap(MAP_FIXED) 覆盖错误页面
信号处理器只读原始原子 不调用 OnceLock/Option 等非 async-signal-safe 抽象

测试

  • 新增 test_concurrent_open_installs_handler_once: 8 线程并发 open 5 种 variant,验证无崩溃
  • 原有 12 个 mmap_reader 测试全部通过

commit

dad5f5a fix(bench): eliminate SIGBUS handler static mut UB with Once + raw atomics

## 修复方案 经 Oracle 审核后采用 **Once + 原始原子变量** 方案,消除 `static mut` UB。 ### 核心改动 (`crates/bench/src/mmap_reader.rs`) | 改动 | 说明 | |------|------| | `static mut OLD_SIGBUS_HANDLER` → `AtomicU8` + `AtomicPtr` | 消除并发写入 UB | | `install_sigbus_handler()` 用 `Once::call_once` | 保证多线程只安装一次 | | 查询 → 发布原子 → 安装 handler | 消除 handler-active-but-state-unpublished 竞态窗口 | | `si_addr` 页对齐 `& !0xFFF` | 防止 mmap(MAP_FIXED) 覆盖错误页面 | | 信号处理器只读原始原子 | 不调用 OnceLock/Option 等非 async-signal-safe 抽象 | ### 测试 - 新增 `test_concurrent_open_installs_handler_once`: 8 线程并发 open 5 种 variant,验证无崩溃 - 原有 12 个 mmap_reader 测试全部通过 ### commit `dad5f5a` fix(bench): eliminate SIGBUS handler static mut UB with Once + raw atomics
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: dailz/logViewer#33