fix: Unity launch waits reliably during slow startup and restart#1339
Conversation
Restart and quit previously continued immediately after sending Kill, which let Windows keep Temp files locked while launch tried to clean them. Poll the project process scan until the killed Unity process disappears before returning quit success or starting a replacement Editor.
Give launch a ten-minute readiness window so slow Unity startup, imports, and domain reloads do not fail after the shared tool readiness timeout. Classify launch readiness timeouts separately from generic reachability failures, and keep explicit CLI/package protocol mismatches on the existing update-required path.
Keep internal readiness probe deadlines classified as launch startup timeouts instead of treating them as caller cancellation, and apply the restart/quit exit deadline to process scans so launch cannot hang past the intended wait.
Limit launch startup timeout wrapping to the running-Editor not-responding path, and return a structured retryable error when restart or quit waits too long for the killed Unity process to exit.
📝 WalkthroughWalkthroughIntroduces two typed timeout errors ( ChangesUnity Launch Timeout Errors and Readiness Refactor
Sequence Diagram(s)sequenceDiagram
participant runLaunch
participant waitForUnityProcessExitForLaunch
participant waitForUnityStartupMarkerForLaunch
participant waitForLaunchReadiness
participant waitForToolReadinessWithTimeout
participant classifyError
rect rgba(255, 200, 100, 0.5)
Note over runLaunch: Restart path
runLaunch->>waitForUnityProcessExitForLaunch: poll until PID disappears
waitForUnityProcessExitForLaunch-->>runLaunch: ok or launchProcessExitTimeoutError
runLaunch->>classifyError: on timeout error → errorCodeUnityProcessExitTimeout
end
rect rgba(100, 200, 255, 0.5)
Note over runLaunch: Fresh start / existing process
runLaunch->>waitForUnityStartupMarkerForLaunch: poll for lockfile
runLaunch->>waitForLaunchReadiness: wait with launch timeout
waitForLaunchReadiness->>waitForToolReadinessWithTimeout: delegate with timeout
waitForToolReadinessWithTimeout-->>waitForLaunchReadiness: ok, cli_update_required (fast-exit), or timeout
waitForLaunchReadiness-->>runLaunch: ok or launchStartupTimeoutError
runLaunch->>classifyError: on timeout error → errorCodeUnityStartupTimeout
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~50 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
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. Comment |
There was a problem hiding this comment.
🧹 Nitpick comments (1)
cli/internal/cli/launch_test.go (1)
428-430: ⚡ Quick winAssert kill invocation in quit/restart exit-wait tests.
Line 428 and Line 478 stub
killUnityProcessForLaunchbut never assert it was called. AddkilledPidchecks so these tests fail if kill is accidentally skipped.Suggested patch
func TestRunLaunchQuitWaitsForKilledUnityProcess(t *testing.T) { @@ - waitedPid := 0 + killedPid := 0 + waitedPid := 0 @@ killUnityProcessForLaunch = func(pid int) error { + killedPid = pid return nil } @@ if code != 0 { t.Fatalf("exit code mismatch: %d stderr=%s", code, stderr.String()) } + if killedPid != 333 { + t.Fatalf("quit killed pid mismatch: %d", killedPid) + } if waitedPid != 333 { t.Fatalf("quit waited pid mismatch: %d", waitedPid) } @@ func TestRunLaunchRestartReportsProcessExitWaitFailure(t *testing.T) { @@ resolverCalled := false + killedPid := 0 @@ killUnityProcessForLaunch = func(pid int) error { + killedPid = pid return nil } @@ if resolverCalled { t.Fatal("restart should not launch a new Unity process before the old one exits") } + if killedPid != 444 { + t.Fatalf("restart killed pid mismatch: %d", killedPid) + } if !strings.Contains(stderr.String(), "still exiting") { t.Fatalf("stderr should include wait failure: %s", stderr.String()) } }Also applies to: 478-480
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@cli/internal/cli/launch_test.go` around lines 428 - 430, The tests at cli/internal/cli/launch_test.go lines 428-430 and lines 478-480 stub the killUnityProcessForLaunch function but do not verify it was actually called. At each location, add a killedPid variable to capture the pid argument when the stub is invoked, then add assertions after the test execution to verify that killedPid contains the expected process ID, ensuring the test fails if the kill invocation is accidentally skipped.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Nitpick comments:
In `@cli/internal/cli/launch_test.go`:
- Around line 428-430: The tests at cli/internal/cli/launch_test.go lines
428-430 and lines 478-480 stub the killUnityProcessForLaunch function but do not
verify it was actually called. At each location, add a killedPid variable to
capture the pid argument when the stub is invoked, then add assertions after the
test execution to verify that killedPid contains the expected process ID,
ensuring the test fails if the kill invocation is accidentally skipped.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0d956882-1d15-4e55-b450-0213f82c6c40
📒 Files selected for processing (8)
cli/internal/cli/error_envelope.gocli/internal/cli/error_envelope_test.gocli/internal/cli/launch.gocli/internal/cli/launch_process_exit_timeout_error.gocli/internal/cli/launch_startup_timeout_error.gocli/internal/cli/launch_test.gocli/internal/cli/tool_readiness.gocli/internal/cli/tool_readiness_test.go
Summary
uloop launchnow gives slow Unity startup, imports, and domain reloads a longer readiness window before failing.User Impact
uloop launch -randuloop launch --quitare less likely to race Windows file locks from a still-exiting Unity process.Changes
Verification
go test ./internal/cli -run 'TestRunLaunch|TestWaitForLaunchReadiness|TestWaitForUnityProcessExit|TestWaitForUnityStartupMarker|TestWaitForToolReadiness|TestToolReadinessDoneError|TestClassify(LaunchStartupTimeout|LaunchProcessExitTimeout|UnityServerNotResponding|CliUpdateRequired)|TestExecuteDynamicCodeReadinessProbeParamsUseForegroundWarmup'scripts/check-go-cli.sh/mnt/c/Users/booql/oss/unity-cli-loop/cli/dist/windows-amd64/uloop.exe --project-path 'C:\Users\booql\oss\cli-loop-tetris' launch -rcodex-review v3-beta