fix(phase2): llc worker 改用 CreateProcessA 替代 system,修 asan 并发挂起

插桩证实:ClassArrayTest 固定 llc 失败是 e5fb16127bce8f68 的 worker 卡在
stdlib.system() 内(LLC2 未打印,Result 保持 -1)。Python 复现 os.system
并发无问题,差异仅剩 asan 构建环境——Windows asan 的 RTL allocator hook
经 CreateProcess 启动子进程时受干扰(LLVM issue #111166 同类)。
新增 _run_cmd_wait:CreateProcessA 直接执行 + WaitForSingleObject +
GetExitCodeProcess,继承父控制台输出(同 system 语义),全 stdlib/栈分配
线程安全。含 [LLC-DBG] 插桩,验证后移除。
This commit is contained in:
TermiNexus committed 2026-08-19 20:57:52 +08:00
1 parent f3c94917e5
commit 70c88107ce
1 file changed
+42 -2
+42 -2
View File
@@ -9,6 +9,8 @@ import vthreading
import w32.fileio as fileio
import w32.win32file
import w32.win32base
import w32.win32process as win32process
import w32.win32sync as win32sync
import subprocess
import viperlib
import ast
@@ -506,6 +508,44 @@ def free_llc_task(task: LlcTask | t.CPtr):
task.ModuleSha1 = None
def _run_cmd_wait(cmd: str) -> int:
"""CreateProcessA 同步执行命令并等待退出,返回退出码。
替代 stdlib.system:Windows asan 环境下 cmd /c 经 CreateProcess 受
RTL allocator hook 干扰可能挂起(LLVM issue #111166 同类,ClassArrayTest
llc 固定卡死根因);CreateProcessA 直接执行目标程序并继承父进程控制台
(stdout/stderr 直接显示,同 system 语义)。全 stdlib.malloc/栈分配,
worker 线程安全。
"""
if cmd is None:
return -1
cl_len: t.CSizeT = string.strlen(cmd)
cmd_line: bytes = stdlib.malloc(cl_len + 1)
if cmd_line is None:
return -1
string.strcpy(cmd_line, cmd)
sa: w32.win32base.SECURITY_ATTRIBUTES = w32.win32base.SECURITY_ATTRIBUTES()
si: win32process.STARTUPINFOA = win32process.STARTUPINFOA()
pi: win32process.PROCESS_INFORMATION = win32process.PROCESS_INFORMATION()
sa.nLength = w32.win32base.SECURITY_ATTRIBUTES.__sizeof__()
sa.lpSecurityDescriptor = t.CPtr(0)
sa.bInheritHandle = 1
si.cb = win32process.STARTUPINFOA.__sizeof__()
# create_flags=0:子进程继承父控制台(输出直接显示,同 system 语义)
ok: int = win32process.CreateProcessA(
t.CPtr(0), cmd_line, t.CPtr(0), t.CPtr(0), 1, 0,
t.CPtr(0), t.CPtr(0), t.CPtr(c.Addr(si)), t.CPtr(c.Addr(pi)))
stdlib.free(cmd_line)
if ok == 0:
return -1
win32sync.WaitForSingleObject(pi.hProcess, w32.win32base.INFINITE)
exit_code: t.CUInt32T = 0
win32process.GetExitCodeProcess(pi.hProcess, t.CPtr(c.Addr(exit_code)))
w32.win32base.CloseHandle(pi.hProcess)
w32.win32base.CloseHandle(pi.hThread)
return t.CInt(exit_code)
def _llc_task_worker(arg: t.CPtr) -> t.CPtr:
"""llc 线程入口:只调 stdlib.system(),不做任何分配(线程安全)
Result 仅在命令链执行完后写入(初始 -1;join 超时保持 -1 → 报失败)"""
@@ -518,14 +558,14 @@ def _llc_task_worker(arg: t.CPtr) -> t.CPtr:
(task.LlcCmd if task.LlcCmd is not None else "?"))
#endregion
if task.OptCmd is not None:
opt_rc: int = stdlib.system(task.OptCmd)
opt_rc: int = _run_cmd_wait(task.OptCmd)
#region debug-point LLC1
stdio.printf("[LLC-DBG] opt rc=%d\n", opt_rc)
#endregion
if opt_rc != 0:
task.Result = 1
return t.CPtr(0)
llc_rc: int = stdlib.system(task.LlcCmd)
llc_rc: int = _run_cmd_wait(task.LlcCmd)
#region debug-point LLC2
stdio.printf("[LLC-DBG] llc rc=%d sha1=%s\n", llc_rc,
(task.ModuleSha1 if task.ModuleSha1 is not None else "?"))