Repository navigation
test(harness): check fixture exit codes; fix exec signal exit codes and a ctrl-c panic - #50
Merged
Merged
Conversation
tobert
added a commit
that referenced
this pull request
Oct 24, 2026
🤖 Claude <claude@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Why: a kaibo review of AGENTS.md (#49) found that checkProcess never compared Expect.ExitCode. Nine fixtures set it; none was tested. Amy: "yes, go ahead on a test PR if we found some gaps." Approach: checkProcess compares the exit code when the process exited on its own (a killed process reports -1). Fixture fixes: #360 now uses ExitCode: 42 in place of a CheckFunc; "protocol: bad config" with --fail expects 1. The three exec signal fixtures expect the shell convention, 128 + signal: 130 for SIGINT, 137 for SIGKILL. Their old values (2 and 0) were never checked and match no rule. Learned: otel-cli exits 255 when the exec child dies from a signal. ProcessState.ExitCode() is -1, and os.Exit(-1) is 255. Next: this commit fails on purpose (3 signal fixtures); the fix follows. 🤖 Claude <claude@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Why: the harness now checks exit codes, and three exec fixtures showed otel-cli exits 255 when its child dies from a signal (Ctrl-C forwarded, or --command-timeout). ProcessState.ExitCode() is -1 for a signaled child, and os.Exit(-1) is 255, so scripts lose the signal. Approach: when ProcessState.Sys() is a syscall.WaitStatus and Signaled(), exit 128 + signal, as bash does: SIGINT 130, SIGKILL 137. WaitStatus exists on Windows too (Signaled is always false); windows, darwin and freebsd cross-build. Learned: --command-timeout kills with SIGKILL (exec.CommandContext), so a timeout exits 137, not timeout(1)'s 124. Next: Amy decides whether 128 + signal is the behavior to keep. Verified: go vet, go test ./... green; `otel-cli exec --command-timeout 50ms -- sleep 1` exits 137; `exec -- sh -c 'exit 3'` exits 3. 🤖 Claude <claude@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Owner
Author
|
kaibo review (cast Applied:
Confirmed correct: 128 + signal on Linux, darwin and freebsd. Not fixed here, verified and pre-existing:
🤖 Generated with Claude Code |
Why: kaibo (deepseek) review of #50. The server timer sets TimedOut even when otel-cli exits on its own (main_test.go:446-456), so the TimedOut guard could skip a real exit code. CommandFailed alone means "no exit code". Approach: guard on !CommandFailed only. Removed the "protocol: bad config" ExecExitCode: 1 expectation: Diagnostics.ToStringMap omits exec_exit_code and only exec writes it, so it checked nothing. CHANGELOG notes the fix is Unix-only (WaitStatus.Signaled is always false on Windows). Learned: exec.go closes the signals channel while signal.Notify is still registered; a second SIGINT during export can panic. Pre-existing, not fixed here. Next: Amy's call on the signal.Stop fix. Verified: go vet, go test (3 consecutive runs green). 🔍 Reviewed-by: DeepSeek (kaibo, deepseek cast) 🤖 Claude <claude@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…anicked Why: the kaibo review of #50 found that exec.go closes the signals channel while signal.Notify is still registered. Amy: "it can go in pr 50". Approach: test first. New fixture "exec ctrl-c during export does not panic": /bin/true exits, the export to a stopped server retries for up to --timeout 1s, and the harness sends SIGINT at 200ms. Before the fix it exits 2 with "panic: send on closed channel" (reproduced by hand too). Fix: signal.Stop(signals) before close(signals). SIGINT during export now has its default action, so otel-cli stops and the span is not sent. Learned: a hand repro from a bash background job exits 0, not 130. Background jobs start with SIGINT ignored, and after signal.Stop Go returns to the inherited ignore. Next: review. Verified: go vet, go test ./... green 3 runs in a row; fixture red before the fix. 🤖 Claude <claude@anthropic.com> Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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.
The functional test harness never compared
Expect.ExitCode. Nine fixtures set it, and none was tested. With the check on, three fixtures showed a real bug:otel-cli execexits 255 when its child is killed by a signal.Behavior change for review:
execnow exits 128 + signal for a signaled child, which is the shell convention: 130 for Ctrl-C, 137 for--command-timeout(SIGKILL). Before, it exited 255. Scripts can see this change. The alternative is to keep 255 and pin it in the fixtures.What changed:
main_test.go:checkProcesscompares the exit code when the process exited on its own. A killed process reports -1, so it is skipped.data_for_test.go: the #360 fixture usesExitCode: 42in place of aCheckFunc; "protocol: bad config" with--failexpects 1. The three signal fixtures expect 130 and 137. Their old values (2 and 0) were never checked.otelcli/exec.go:128 + status.Signal()whenProcessState.Sys()is asyscall.WaitStatusandSignaled().otelcli/exec.go:signal.Stop(signals)beforeclose(signals). Before, a Ctrl-C during the span export panicked with "send on closed channel" (exit 2). Now SIGINT has its default action. The new fixture "exec ctrl-c during export does not panic" was red before the fix.Commits are test-first: each fix follows a failing fixture.
Verification:
Found by the kaibo review of AGENTS.md on #49. After this merges, the AGENTS.md hazard "the harness ignores
Expect.ExitCode" is no longer true; #49 drops it.🤖 Generated with Claude Code