Skip to content

Fix Starlark CPU profiler resource leaks in Main and BlazeCommandDispatcher#29558

Open
SebTardif wants to merge 1 commit into
bazelbuild:masterfrom
SebTardif:fix-starlark-cpu-profile-cleanup
Open

Fix Starlark CPU profiler resource leaks in Main and BlazeCommandDispatcher#29558
SebTardif wants to merge 1 commit into
bazelbuild:masterfrom
SebTardif:fix-starlark-cpu-profile-cleanup

Conversation

@SebTardif
Copy link
Copy Markdown

@SebTardif SebTardif commented May 16, 2026

Problem

Two resource management bugs exist in the Starlark CPU profiling lifecycle:

1. Main.java (-cpuprofile flag)
The output stream is opened before checking whether profiling startup succeeded. stopCpuProfile() is called unconditionally even when startCpuProfile() returns false (native support unavailable), which can trigger a stop without start error. The output stream is also leaked on failure.

2. BlazeCommandDispatcher.java (--starlark_cpu_profile flag)
The output stream created for the profile is leaked on several early return paths:

  • IllegalStateException from startCpuProfile() (e.g. SIGPROF in use)
  • Early exit from option parsing errors or module beforeCommand failures
  • Uncaught exceptions reaching the finally block

Additionally, if stopCpuProfile() throws IOException in the normal finalization path, the finally block could attempt a second stop, retriggering a stop without start error.

Fix

Main.java:

  • Track whether startCpuProfile() actually succeeded
  • Only call stopCpuProfile() when it did; otherwise close the output stream directly
  • Wrap the logic in try/finally for proper cleanup
  • Extract a package-local run() method so the logic is testable without System.exit()

BlazeCommandDispatcher.java:

  • Track both the output stream and the profiling-started boolean as local variables
  • Close the output stream on the startCpuProfile() exception path
  • Add cleanup in the finally block: stop profiling if started, or close the stream if not
  • Clear both tracking variables after successful stop to prevent double-stop on IOException
  • Add a helper closeStarlarkCpuProfileOutput() for safe stream cleanup

Tests

  • MainTest (src/test/java/net/starlark/java/cmd/MainTest.java): Verifies -cpuprofile does not fail when profiling is unsupported (native support set to null).
  • BlazeCommandDispatcherTest: Two new methods:
    • starlarkCpuProfileOutputIsClosedWhenProfilingInitializationFails: Uses a fake native support where startTimer() returns false; verifies the output stream is closed and the correct failure code is returned.
    • starlarkCpuProfileOutputIsClosedOnEarlyReturnAfterStart: Uses a fake native support where startTimer() succeeds; triggers an early exit via --config=UNDEFINED_CONFIG_VALUE; verifies the output stream is closed.

@github-actions github-actions Bot added team-Rules-Server Issues for serverside rules included with Bazel team-Starlark-Interpreter Issues involving the Starlark interpreter used by Bazel awaiting-review PR is awaiting review from an assigned reviewer labels May 16, 2026
…atcher

Fix two resource management bugs in the Starlark CPU profiling lifecycle:

1. In Main.java (-cpuprofile flag): The output stream was opened before
   checking whether profiling startup succeeded, and stopCpuProfile()
   was called unconditionally even when startCpuProfile() returned false
   or the native support was unavailable. This could trigger a
   'stop without start' error. Refactored to track startup success
   explicitly and only stop/close on the appropriate paths.

2. In BlazeCommandDispatcher.java (--starlark_cpu_profile flag): The
   output stream created for the profile was leaked on several early
   return paths (e.g. IllegalStateException from startCpuProfile,
   early exit from option parsing errors, or uncaught exceptions).
   Added proper cleanup in the finally block and on the init-failure
   path, and ensured stopCpuProfile() is not called twice if it
   throws IOException.

Also extracted Main logic into a package-local run() method to make
it testable without System.exit().

Tests:
- MainTest: verifies -cpuprofile does not fail when profiling is
  unsupported (native support is null).
- BlazeCommandDispatcherTest: verifies output stream is closed when
  profiling initialization fails (startTimer returns false) and when
  the command exits early after successful profiling start.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>
@SebTardif SebTardif force-pushed the fix-starlark-cpu-profile-cleanup branch from 55e5c39 to b5f3510 Compare May 16, 2026 17:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

awaiting-review PR is awaiting review from an assigned reviewer team-Rules-Server Issues for serverside rules included with Bazel team-Starlark-Interpreter Issues involving the Starlark interpreter used by Bazel

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant