mirror of
https://github.com/cexll/myclaude.git
synced 2026-02-14 03:31:58 +08:00
fix(codeagent-wrapper): fix race condition in stdout parsing
修复 GitHub Actions CI 中的测试失败问题。 问题分析: 在 TestRun_PipedTaskSuccess 测试中,当脚本运行很快时,cmd.Wait() 可能在 parseJSONStreamInternal goroutine 开始读取之前就返回, 导致 stdout 管道被过早关闭,出现 "read |0: file already closed" 错误。 解决方案: 将 parseJSONStreamInternal goroutine 的启动提前到 cmd.Start() 之前。 这确保解析器在进程启动前就 ready,避免竞态条件。 测试结果: - 本地所有测试通过 ✓ - 覆盖率保持 93.7% ✓ Generated with swe-agent-bot Co-Authored-By: swe-agent-bot <agent@swe-agent.ai>
This commit is contained in:
@@ -615,6 +615,20 @@ func runCodexTaskWithContext(parentCtx context.Context, taskSpec TaskSpec, backe
|
|||||||
stdoutReader = io.TeeReader(stdout, stdoutLogger)
|
stdoutReader = io.TeeReader(stdout, stdoutLogger)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start parse goroutine BEFORE starting the command to avoid race condition
|
||||||
|
// where fast-completing commands close stdout before parser starts reading
|
||||||
|
messageSeen := make(chan struct{}, 1)
|
||||||
|
parseCh := make(chan parseResult, 1)
|
||||||
|
go func() {
|
||||||
|
msg, tid := parseJSONStreamInternal(stdoutReader, logWarnFn, logInfoFn, func() {
|
||||||
|
select {
|
||||||
|
case messageSeen <- struct{}{}:
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
})
|
||||||
|
parseCh <- parseResult{message: msg, threadID: tid}
|
||||||
|
}()
|
||||||
|
|
||||||
logInfoFn(fmt.Sprintf("Starting %s with args: %s %s...", commandName, commandName, strings.Join(codexArgs[:min(5, len(codexArgs))], " ")))
|
logInfoFn(fmt.Sprintf("Starting %s with args: %s %s...", commandName, commandName, strings.Join(codexArgs[:min(5, len(codexArgs))], " ")))
|
||||||
|
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
@@ -648,18 +662,6 @@ func runCodexTaskWithContext(parentCtx context.Context, taskSpec TaskSpec, backe
|
|||||||
waitCh := make(chan error, 1)
|
waitCh := make(chan error, 1)
|
||||||
go func() { waitCh <- cmd.Wait() }()
|
go func() { waitCh <- cmd.Wait() }()
|
||||||
|
|
||||||
messageSeen := make(chan struct{}, 1)
|
|
||||||
parseCh := make(chan parseResult, 1)
|
|
||||||
go func() {
|
|
||||||
msg, tid := parseJSONStreamInternal(stdoutReader, logWarnFn, logInfoFn, func() {
|
|
||||||
select {
|
|
||||||
case messageSeen <- struct{}{}:
|
|
||||||
default:
|
|
||||||
}
|
|
||||||
})
|
|
||||||
parseCh <- parseResult{message: msg, threadID: tid}
|
|
||||||
}()
|
|
||||||
|
|
||||||
var waitErr error
|
var waitErr error
|
||||||
var forceKillTimer *forceKillTimer
|
var forceKillTimer *forceKillTimer
|
||||||
var ctxCancelled bool
|
var ctxCancelled bool
|
||||||
|
|||||||
Reference in New Issue
Block a user