Skip to content

Commit 2391d67

Browse files
committed
fix(pkg): libuv windows -DNDEBUG — EventLoop uv_walk double-close (redis-plus-plus#575)
Windows async teardown asserts in libuv src/win/handle.c:71: EventLoop's LoopDeleter uv_walk re-closes handles already uv_close'd by hiredis's libuv adapter cleanup (on Windows they stay in the loop's handle queue; on unix the closing phase unlinks them first). uv_close's UV_HANDLE_CLOSING guard makes the second call a harmless no-op — only the assert(0) aborts. NDEBUG matches libuv release builds (vcpkg/conan) and disables the assert. Upstream open issue sewenew/redis-plus-plus#575; caught by PR #195 windows workspace leg.
1 parent 1f12571 commit 2391d67

2 files changed

Lines changed: 20 additions & 1 deletion

File tree

.agents/docs/2026-08-09-add-redis-plus-plus-plan.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,3 +123,13 @@ include 布局(镜像上游 target_include_directories):
123123
- `<uv.h>``<hiredis/adapters/libuv.h>` 经 feature 激活后的依赖 include 传播到达。
124124
- **测试**:新成员 `redis-plus-plus-async`(1.3.13 + `features=["async"]`),进程内迷你 RESP server **解析完整 RESP 数组**(异步客户端会把 PING+SET 管道进同一 TCP 段),驱动 `AsyncRedis`(EventLoop 后台线程跑 `uv_run`),`.get()` 阻塞取回 `PONG`/OK。钉版 mcpp 本地通过。
125125
- **负向**:不启用 async 时,async 符号不存在(现有同步成员不受影响,三成员全绿)。
126+
127+
### 8.3 Windows 修复:libuv `-DNDEBUG`(上游 redis-plus-plus#575)
128+
129+
**CI 现象**(PR #195 windows 腿):async 测试运行期崩溃
130+
`Assertion failed: 0, src/win/handle.c:71`(exit 0xC0000409)。
131+
132+
**根因**(与上游 open issue [sewenew/redis-plus-plus#575](https://github.com/sewenew/redis-plus-plus/issues/575) 同一 bug,作者仅 Windows 可复现,与我们的 linux/mac 全绿一致):
133+
`EventLoop::LoopDeleter` 析构时 `uv_walk` 对所有 handle 调 `uv_close`,其中**已被 hiredis libuv adapter cleanup 关过的 poll/timer handle** 在 Windows 上仍留在 loop 的 handle 队列(Unix 上 closing 阶段先跑完、handle 已摘链),于是二次 `uv_close` 命中 `UV_HANDLE_CLOSING` guard 里的 `assert(0)`。libuv 的二次 close 本身有 guard 会直接 return(无害),只有断言在非 NDEBUG 构建下 abort。
134+
135+
**修复**:`compat.libuv` windows `cflags``-DNDEBUG`(与 vcpkg/conan 的 libuv release 构建一致),guard 生效、二次 close 变 no-op;不加不会改变 unix 行为(unix 不发生二次 close)。已在描述符注释中写明并指向 #575

pkgs/c/compat.libuv.lua

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,16 @@ package = {
9999
-- src/win/ is library code; tests live in test/).
100100
windows = {
101101
sources = { "*/src/win/*.c" },
102-
cflags = { "-DWIN32_LEAN_AND_MEAN", "-D_WIN32_WINNT=0x0602", "-D_CRT_DECLARE_NONSTDC_NAMES=0" },
102+
-- NDEBUG: upstream redis-plus-plus#575 — EventLoop::LoopDeleter's
103+
-- uv_walk re-closes handles already uv_close'd by hiredis's libuv
104+
-- adapter cleanup (on Windows they are still in the loop's handle
105+
-- queue at teardown, unlike unix where the closing phase runs
106+
-- first). uv_close has a UV_HANDLE_CLOSING guard that makes the
107+
-- second call a harmless no-op; only the assert(0) aborts, so a
108+
-- release-style build (NDEBUG, matching vcpkg/conan libuv) fixes
109+
-- it. Unfixable package-side otherwise without shadowing
110+
-- event_loop.cpp. Regression: PR #195 windows workspace leg.
111+
cflags = { "-DWIN32_LEAN_AND_MEAN", "-D_WIN32_WINNT=0x0602", "-D_CRT_DECLARE_NONSTDC_NAMES=0", "-DNDEBUG" },
103112
ldflags = { "-lpsapi", "-luser32", "-ladvapi32", "-liphlpapi", "-luserenv", "-lws2_32", "-ldbghelp", "-lole32", "-lshell32" },
104113
},
105114
},

0 commit comments

Comments
 (0)