Repository navigation
refactor(server): 构造路径原子化 —— out-param 一次建立、单一移交点、错误码如实 - #475
Merged
Merged
Conversation
v2.10 roadmap d5(构造/释放原子化)。create_simple_server_internal(builder 构造入口)原来的形状: - out-param `*server = NULL` 在 5 个分支里各自写一遍 - 两个失败分支手工置 `server->config/router = NULL`(其中三处是无操作—— 那两项的所有权要到后面才移交),还要靠一条 "Do NOT null them here" 注释 防止后人"修好"唯一不能置空的分支 - 加上一个只写不读的死字段 `auto_cleanup` ## 新形状 1. **out-param 不变式一次建立**:函数头部 `*server = NULL`,所有失败路径天然 成立,不再靠每个分支自觉 2. **单一移交点**:server/router/config 三个子对象由局部变量持有到唯一的 handover 点(builder->server/router/config 与 server->config/router 在 同一处赋值)。此前每个失败分支只释放自己命名的对象 —— 任何分支都不需要 从 server 手里"取消拥有",这是那堆手工置 NULL 存在的根本原因 3. **builder 是视图不是所有者**:移交之后 server_free 一并释放三者,builder 结构体只持句柄。头文件已写明这条语义 4. **错误码如实**:listen 失败不再一律塌缩成 SERVER_LISTEN —— NULL host 是 调用方错误(INVALID_PARAM),端口占用是运行时错误(SERVER_LISTEN),两者 的修复动作不同 5. 删除死字段 `auto_cleanup`(只写不读,命中"字段要么权威要么不存在") ## 测试 test_server_atomic_construct 新增 3 个用例,两条不变式均经变异验证: - **out-param 契约**:用哨兵值 0x1 初始化 out-param 再断言被写成 NULL。 (第一版用 nullptr 初始化,变异测试当场揭穿它没牙齿——函数压根不写, 测试也绿。) 变异:删掉头部的 `*server = NULL` → 该用例红 - **listen 失败清理**:占位端口制造 EADDRINUSE(与运行身份无关),断言返回 SERVER_LISTEN、out-param 为 NULL。变异:把清理改回旧形状(先置 NULL 再 free)→ ASan 抓到 config(56B) + router(120B) 泄漏 - **视图语义**:断言三个句柄在移交点指向同一批对象,并走 simple_free 全程 (若 builder 也拥有它们,这里是 double free) 验证:ctest 120/120(默认构建 + ASan 全量);cppcheck 零告警;test-validity 门禁 PASS;门禁口径内文件 clang-format 18.1.8 合规。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
v2.10 roadmap d5(构造/释放原子化)。对象是
create_simple_server_internal—— builder 构造入口uvhttp_server_create/uvhttp_serve的背后实现。原来的形状
*server = NULL在 5 个分支里各自写一遍server->config/router = NULL—— 其中三处其实是无操作(那两项的所有权要到后面才移交),还要靠一条Do NOT null them here的注释防止后人"修好"唯一不能置空的分支auto_cleanup即 brain 记录的那条:正确性靠注释维护。
新形状
*server = NULL,所有失败路径天然成立server/router/config三个子对象由局部变量持有到唯一 handover 点(builder->*与server->*在同一处赋值)。此前每个失败分支只释放自己命名的对象,任何分支都不需要从 server 手里"取消拥有" —— 这正是那堆手工置 NULL 存在的根本原因uvhttp_server_free一并释放三者;头文件写明该语义SERVER_LISTEN:NULL host 是调用方错误(INVALID_PARAM),端口占用是运行时错误(SERVER_LISTEN),两者修复动作不同auto_cleanup(只写不读,命中「字段要么权威要么不存在」)测试(两条不变式均经变异验证)
test_server_atomic_construct+3:0x1初始化 out-param,断言被写成 NULL。第一版用nullptr初始化,变异测试当场揭穿它没牙齿——函数压根不写 out-param,测试也绿。变异:删掉头部的*server = NULL→ 该用例红SERVER_LISTEN+ out-param 为 NULL。变异:把清理改回旧形状(先置 NULL 再 free)→ ASan 抓到 config(56B) + router(120B) 泄漏simple_free(若 builder 也拥有它们,此处即 double free)验证
ctest 120/120(默认构建 + ASan 全量);cppcheck 零告警;test-validity 门禁 PASS;门禁口径内文件 clang-format 18.1.8 合规。