Skip to content

Docker Compose ProcessRunner can hang or leave orphan processes - #50963

Merged
wilkinsona merged 2 commits into
spring-projects:4.0.xfrom
SebTardif:fix/processrunner-reader-latch-destroy
Sep 2, 2026
Merged

Docker Compose ProcessRunner can hang or leave orphan processes#50963
wilkinsona merged 2 commits into
spring-projects:4.0.xfrom
SebTardif:fix/processrunner-reader-latch-destroy

Conversation

@SebTardif

Copy link
Copy Markdown
Contributor

Summary

ProcessRunner can hang forever if a stream reader fails, and can leave orphan Docker Compose child processes when waitFor is interrupted.

Problem

ReaderThread only calls CountDownLatch.countDown() on the success path. If reading fails with IOException, or if the optional outputConsumer throws, the latch is never released. After the child process exits, ProcessRunner.run blocks forever on latch.await() in ReaderThread.toString().

Separately, when process.waitFor() is interrupted, the interrupt flag is restored and an exception is thrown (fixed in #50451), but the child process is not destroyed. Docker Compose commands can remain as orphans.

Change

  • Move latch.countDown() into a finally block in ReaderThread.run().
  • Call process.destroy() after restoring the interrupt flag when waitFor is interrupted.

Failure scenario

  1. Docker Compose support runs a process via ProcessRunner.run(consumer, command...).
  2. The consumer throws (or stream read fails) after partial output.
  3. The process exits, but the reader never counts down the latch.
  4. The calling thread blocks indefinitely on toString() / await().

For interrupt: a long-running compose command is interrupted during waitFor; without destroy(), the child keeps running after the Spring Boot thread has aborted.

Origin

Introduced with Docker Compose support in 842e17ecedaf (2023-04-07, Moritz Halbritter). Present for ~3 years. Related prior fix: #50451 (interrupt flag restore only).

Validation

  • Red/green:
    • runWhenOutputConsumerThrowsDoesNotHang: timed out without the latch fix; passes with it.
    • runWhenInterruptedDestroysChildProcess: child sleep stayed alive without destroy; process is dead with the fix.
  • ./gradlew :core:spring-boot-docker-compose:test --tests ProcessRunnerTests
  • checkFormatMain / checkFormatTest / checkstyleMain / checkstyleTest

Related

@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged label Jul 16, 2026
@wilkinsona wilkinsona added status: waiting-for-feedback We need additional information before we can continue type: bug A general bug and removed status: waiting-for-feedback We need additional information before we can continue status: waiting-for-triage An issue we've not yet triaged labels Aug 26, 2026
@wilkinsona wilkinsona added this to the 4.0.x milestone Sep 2, 2026
@wilkinsona wilkinsona self-assigned this Sep 2, 2026
Release the output reader latch in a finally block so a failing stream
read or output consumer cannot leave ProcessRunner.run blocked on
CountDownLatch.await after the child process has exited.

Destroy the child process when waitFor is interrupted so Docker Compose
commands are not left running as orphans.

Signed-off-by: Sebastien Tardif <sebtardif@ncf.ca>

See spring-projectsgh-50963
@wilkinsona
wilkinsona changed the base branch from main to 4.0.x September 2, 2026 08:10
@wilkinsona
wilkinsona force-pushed the fix/processrunner-reader-latch-destroy branch from 70904f7 to 5d71540 Compare September 2, 2026 08:11
…ses"

See spring-projectsgh-50963

Signed-off-by: Andy Wilkinson <andy.wilkinson@broadcom.com>
wilkinsona added a commit to SebTardif/spring-boot that referenced this pull request Sep 2, 2026
@wilkinsona
wilkinsona force-pushed the fix/processrunner-reader-latch-destroy branch from 5d71540 to bf87316 Compare September 2, 2026 08:12
@wilkinsona wilkinsona modified the milestones: 4.0.x, 4.0.9 Sep 2, 2026
@wilkinsona
wilkinsona merged commit 92c3fcf into spring-projects:4.0.x Sep 2, 2026
4 checks passed
@wilkinsona

Copy link
Copy Markdown
Member

Thanks, @SebTardif.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

type: bug A general bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants