Skip to content

fix(standalone): unbounded child log pumps + never-empty version#2167

Open
jlaneve wants to merge 2 commits into
mainfrom
julianlaneve/standalone-pump-hardening
Open

fix(standalone): unbounded child log pumps + never-empty version#2167
jlaneve wants to merge 2 commits into
mainfrom
julianlaneve/standalone-pump-hardening

Conversation

@jlaneve

@jlaneve jlaneve commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Summary

Two hardening fixes found while chasing a local scheduler wedge (whose actual root cause turned out to be machine-level kernel pipe-pool exhaustion, not the CLI; details in the commit message):

  • airflow/standalone.go: the foreground-mode child stdout/stderr pumps used bufio.Scanner, whose default 64KB token limit makes Scan() return false silently on a single long log line. The pump goroutine then exits, the pipe fills, and the child process blocks forever in write(). Airflow's scheduler routinely emits very long single-line records (task lists), so this is a real latent wedge. Replaced with io.Copy, which never stops reading until EOF
  • version/version.go: builds without the Makefile's -ldflags (e.g. plain go install) printed an empty string for astro version. Added an init() fallback chain: module version, then vcs.revision short SHA, then SNAPSHOT

Validation

  • go vet clean
  • ./version and standalone tests pass; the one pre-existing ./airflow failure (TestRegistryLogin, macOS keychain) fails identically on untouched main

🤖 Generated with Claude Code

…version

Two hardening fixes found while debugging a wedged standalone scheduler:

1. startForeground pumped the airflow child's stdout/stderr through
   bufio.Scanner, which silently stops at the first line longer than its
   64KB token limit. If a pump goroutine exits while the child lives, the
   child's 16KB stdout pipe fills and its next write() blocks forever,
   freezing it mid-loop (the scheduler logs task lists that can exceed
   64KB on one line). Use io.Copy, which never stops reading until EOF.
   Background mode was never affected (stdout goes straight to a file).

   Note: the wedge that prompted this investigation turned out to be
   machine-wide kernel pipe-buffer exhaustion (~14k leaked pipe fds held
   by stale terminal sessions starved XNU's pipe KVA pool, making any
   new pipe's first write block system-wide), not this code path. The
   Scanner limit is a real latent wedge of the same shape, fixed here.

2. astro version printed an empty string when the binary was built
   without the Makefile's -ldflags (e.g. plain go build / go install).
   Fall back to Go build info: module version, then vcs revision, then
   plain SNAPSHOT, so the version is never empty.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@jlaneve jlaneve requested a review from a team as a code owner June 10, 2026 03:12
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coveralls-official

Copy link
Copy Markdown

Coverage Report for CI Build 0

Coverage remained the same at 44.776%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: 10 uncovered changes across 1 file (10 of 20 lines covered, 50.0%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
version/version.go 18 8 44.44%
Total (2 files) 20 10 50.0%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 55914
Covered Lines: 25036
Line Coverage: 44.78%
Coverage Strength: 7.75 hits per line

💛 - Coveralls

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