Skip to content

Fix log stream hang after failed cached builds#235

Merged
TorstenDittmann merged 2 commits into
mainfrom
fix/log-stream-missing-runtime
Jun 12, 2026
Merged

Fix log stream hang after failed cached builds#235
TorstenDittmann merged 2 commits into
mainfrom
fix/log-stream-missing-runtime

Conversation

@TorstenDittmann

@TorstenDittmann TorstenDittmann commented Jun 12, 2026

Copy link
Copy Markdown
Contributor

Summary

  • terminate the active logs tail process when a runtime disappears while streaming logs
  • add an E2E regression for failed cache-enabled v5 builds with concurrent /logs

Verification

  • ./vendor/bin/pint --test --config pint.json src/Executor/Runner/Docker.php tests/e2e/ExecutorTest.php
  • docker run --rm --network executor_runtimes -v "$PWD":/app -w /app executor-openruntimes-executor ./vendor/bin/phpunit --configuration phpunit.xml --filter testLogStreamClosesAfterFailedCachedBuild
  • docker run --rm --network executor_runtimes -v "$PWD":/app -w /app executor-openruntimes-executor ./vendor/bin/phpunit --configuration phpunit.xml --testsuite=unit

Negative Control

  • temporarily removed the termination fix, rebuilt the executor, and confirmed testLogStreamClosesAfterFailedCachedBuild failed because /logs stayed open for ~13.57s instead of closing promptly

@greptile-apps

greptile-apps Bot commented Jun 12, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a log-stream hang that occurred when a runtime was removed (e.g., after a failed cached build) while a /logs SSE client was connected: the timer callback now flushes any buffered log chunk and terminates the tail -F process before returning, so the stream closes promptly instead of waiting for the full timeout to expire.

  • Docker.php: In the timer tick that watches $activeRuntimes, a new branch is added for the "runtime no longer present" case — it writes any pending $logsChunk to the response, then calls proc_terminate on $logsProcess (when the handle is available), which unblocks the Console::execute call and allows Timer::clear to run.
  • ExecutorTest.php: A new E2E regression test testLogStreamClosesAfterFailedCachedBuild starts a /logs stream and a failing cached build concurrently, then asserts the stream closes in under 10 seconds and that the build's output is present in the 400 error response.

Confidence Score: 4/5

The fix correctly closes the stream for the primary failure scenario; a fast-failing build that never emits timing data can still leave the stream open until the configured timeout.

The timer callback change is tightly scoped and backed by a negative-control regression test. The proc_terminate call is gated on !empty($logsProcess), meaning a build that completes (or fails) before the tail -F process has had a chance to emit any output — before $logsProcess is set — bypasses the termination path and the stream stays open until $timeout expires.

src/Executor/Runner/Docker.php — specifically the !empty($logsProcess) guard, which is the remaining gap in the fix.

Important Files Changed

Filename Overview
src/Executor/Runner/Docker.php Adds flush-then-terminate logic in the timer callback when the runtime disappears mid-stream; correct for the common case where the tail process handle is already set, but a narrow timing window remains if the process hasn't been initialized yet
tests/e2e/ExecutorTest.php New regression test for failed cached-build log streaming; uses a random runtimeId but a hardcoded destination path and cacheKey that match the existing testLogStream test, creating a latent conflict if tests ever run in parallel

Reviews (2): Last reviewed commit: "fix: flush logs before terminating missi..." | Re-trigger Greptile

Comment thread src/Executor/Runner/Docker.php
Comment thread src/Executor/Runner/Docker.php
@TorstenDittmann TorstenDittmann merged commit 6e9bc15 into main Jun 12, 2026
7 checks passed
@TorstenDittmann TorstenDittmann deleted the fix/log-stream-missing-runtime branch June 12, 2026 10:29
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.

2 participants