Skip to content

ci: capture BDD-target stderr to diagnose and stop the mTLS flake#576

Merged
DavidCozens merged 1 commit into
mainfrom
ci/bdd-capture-target-stderr
Jun 17, 2026
Merged

ci: capture BDD-target stderr to diagnose and stop the mTLS flake#576
DavidCozens merged 1 commit into
mainfrom
ci/bdd-capture-target-stderr

Conversation

@DavidCozens

Copy link
Copy Markdown
Owner

Why

The bdd-windows-otel mTLS scenario intermittently fails with oracle received 0 of 1 messages within 10 seconds. The signature doesn't fit a slow handshake: the service thread retries SolidSyslog_Service in a ~1 ms loop, so within the 10 s wait the sender retries thousands of times — staying at 0 of 1 means the target stalled or died, not "was slow."

Root-cause hypothesis: the target is spawned with stderr=subprocess.PIPE but nothing reads it (only stdout is teed by the reader thread). The target's error handler writes every error event to stderr. Under a transient TLS/mTLS handshake failure that keeps retrying, the undrained pipe fills (~4–64 KB on Windows) and the next write blocks the target inside Service → stall → 0 of N. It's intermittent because it only bites if the handshake hasn't succeeded before the pipe fills, and mTLS is the chattiest handshake. The discarded stderr is also why we currently can't tell a real TLS bug from an environmental flake.

What

Test-harness only — no production/library change:

  • _start_stderr_reader drains the target's stderr into a 16 KB sliding buffer (mirrors _start_stdout_reader, shares its idempotency guard). Draining removes the pipe-full stall.
  • after_step now dumps both stdout (GUEST:) and stderr (ERR:) on failure, so the client-side cause (handshake timeout / cert rejected / connection refused / fatal _Exit) is visible in the behave log.
  • scripts/repro-mtls-flake.ps1 loops the @mtls scenario on a native Windows box (optional -Stress load), saving failing-run logs — to confirm the hypothesis before deciding whether any library/timeout change (e.g. the 200 ms connect timeout, error-spew throttling) is warranted.

Next

Run the repro script on the native Windows box; let the captured ERR: output decide whether any production change is actually needed. DEVLOG entry included.

🤖 Generated with Claude Code

The BDD target is spawned with stderr=PIPE but nothing reads it — only stdout
is teed by the reader thread. The target's error handler writes every error
event to stderr, so under a retrying TLS/mTLS handshake failure (the ~1ms
service loop retries thousands of times in the 10s oracle wait) the undrained
pipe fills; on Windows the next write blocks the target inside Service,
stalling it for the rest of the scenario and producing the intermittent
"oracle received 0 of N messages" flake. The discarded stderr also meant we
couldn't tell a real TLS failure from an environmental one.

- _start_stderr_reader drains the target's stderr into a 16KB sliding buffer
  (mirrors _start_stdout_reader, shares its idempotency guard). Draining
  removes the pipe-full stall.
- after_step dumps both stdout (GUEST:) and stderr (ERR:) on failure, so the
  client-side cause (handshake timeout / cert rejected / connection refused /
  fatal exit) is visible in the behave log.
- scripts/repro-mtls-flake.ps1 loops the @Mtls scenario on a native Windows
  box (optional -Stress load), saving failing-run logs, to confirm the
  hypothesis before any library/timeout change.

Test-side only — no production/library change. DEVLOG entry added.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 17, 2026

Copy link
Copy Markdown
Contributor

Warning

Review limit reached

@DavidCozens, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 23 minutes and 27 seconds. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b6107e7-1579-4010-bb61-17f3368d5776

📥 Commits

Reviewing files that changed from the base of the PR and between 9605afa and 7f88a6a.

📒 Files selected for processing (4)
  • Bdd/features/environment.py
  • Bdd/features/steps/syslog_steps.py
  • DEVLOG.md
  • scripts/repro-mtls-flake.ps1
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch ci/bdd-capture-target-stderr

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions

Copy link
Copy Markdown
Contributor

☀️   Quality Summary

   🚦   build-linux-gcc: 100% successful (✔️ 1521 passed)
   🚦   build-freertos-host-tdd-plustcp: 100% successful (✔️ 1872 passed)
   🚦   build-linux-clang: 100% successful (✔️ 1453 passed)
   🚦   sanitize-linux-gcc: 100% successful (✔️ 1453 passed)
   🚦   integration-linux-openssl: 100% successful (✔️ 16 passed)
   🚦   integration-linux-mbedtls: 100% successful (✔️ 14 passed)
   🚦   integration-windows-openssl: 100% successful (✔️ 16 passed)
   🚦   bdd-linux-syslog-ng: 94% successful (✔️ 49 passed, 🙈 3 skipped)
   🚦   bdd-windows-otel: 88% successful (✔️ 46 passed, 🙈 6 skipped)
   🚦   bdd-freertos-qemu-plustcp: 87% successful (✔️ 45 passed, 🙈 7 skipped)
   🚦   bdd-freertos-qemu-lwip: 87% successful (✔️ 45 passed, 🙈 7 skipped)
   🚦   build-windows-msvc: 100% successful (✔️ 1298 passed)
   🚦   build-linux-tunable-override: 100% successful (✔️ 1453 passed)
   ⚠️   Clang-Tidy: No warnings
   ⚠️   CPPCheck: No warnings


Created by Quality Monitor v1.14.0 (#f3859fd). More details are shown in the GitHub Checks Result.

@DavidCozens DavidCozens merged commit 38d28f4 into main Jun 17, 2026
28 checks passed
@DavidCozens DavidCozens deleted the ci/bdd-capture-target-stderr branch June 17, 2026 14:10
DavidCozens added a commit that referenced this pull request Jun 17, 2026
…#577)

The script used `taskkill /F /IM otelcol-contrib.exe 2>$null` to clear stale
oracles, but with $ErrorActionPreference='Stop' (and PowerShell 5.1's handling
of native-command stderr) the "process not found" message taskkill emits when
nothing is running becomes a terminating error. On a clean box — no leftover
otelcol — the startup cleanup throws before the oracle is ever started, which
surfaced as "not finding the oracle".

Replace both taskkill calls with a PowerShell-native, non-throwing kill:
Get-Process otelcol-contrib -ErrorAction SilentlyContinue | Stop-Process -Force.

Verified: 60/60 @Mtls iterations pass under -Stress on a native Windows box,
confirming the stderr-drain fix (PR #576) holds under load.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant