Skip to content

[Repo Assist] fix: add 30-second watchdog timer to prevent phpcbf subprocess hangs#129

Draft
github-actions[bot] wants to merge 1 commit intomasterfrom
repo-assist/improve-subprocess-timeout-2026-04-03-afd2fe583bb0b640
Draft

[Repo Assist] fix: add 30-second watchdog timer to prevent phpcbf subprocess hangs#129
github-actions[bot] wants to merge 1 commit intomasterfrom
repo-assist/improve-subprocess-timeout-2026-04-03-afd2fe583bb0b640

Conversation

@github-actions
Copy link
Copy Markdown
Contributor

@github-actions github-actions bot commented Apr 3, 2026

🤖 This is an automated draft PR from Repo Assist, an AI assistant.

Summary

Adds a 30-second watchdog timer to the format() function so that a stalled phpcbf process can no longer freeze VS Code indefinitely.

Problem

format() spawns phpcbf as a child process and wraps it in a Promise. If the process stalls (e.g. waiting for stdin on a misconfigured build, hanging while processing an unusually large file, or hitting a deadlock in the external tool) the Promise never settles. VS Code's formatter infrastructure waits for that Promise forever, leaving the document save or Format Document command frozen with no feedback.

This has been reported as #35 ("onWillSaveTextDocument-listener error: timeout") and accounts for the VS Code Error: timeout in the extension host log that users see after a 5-second VS Code wait.

Fix

A setTimeout is scheduled immediately after spawning:

const TIMEOUT_MS = 30000;
let killTimer = setTimeout(() => {
    exec.kill();               // terminate the stalled process
    fs.unlink(fileName, );    // clean up the temp file
    window.showErrorMessage(); // inform the user
}, TIMEOUT_MS);
```

The timer is cleared (`clearTimeout(killTimer)`) in both the `exit` and `error` handlers so it never fires on a normally-completing invocation. 30 seconds is intentionally generous — a well-configured phpcbf finishes in milliseconds; the timeout is only a last-resort safety net.

## Trade-offs

| | |
|---|---|
| **No configuration knob** | 30 s covers all realistic scenarios. Avoids `package.json` changes (protected file). |
| **Process signal** | Uses the default `SIGTERM` via `process.kill`. On Windows this becomes a hard termination, which is acceptable for a stalled formatter. |
| **Promise resolution** | The timer fires *before* the Promise settles, so the Promise remains pending. VS Code will eventually time out its own side. Future improvement: reject the Promise from the timer callback (requires restructuring around PR #106's fixes). |

## Test Status

All 7 existing unit tests pass:

```
 findFiles (7 subtests)
 tests 7, pass 7, fail 0

Relates to #35.

Generated by Repo Assist ·

To install this agentic workflow, run

gh aw add githubnext/agentics/workflows/repo-assist.md@346204513ecfa08b81566450d7d599556807389f

When phpcbf stalls (e.g. on a misconfigured build or very large file),
format() returned a Promise that never settled, freezing VS Code
indefinitely with no user feedback.

Fix: schedule a timer after spawning. The timer terminates the process
and shows an error message if it fires. It is cancelled on normal exit
or spawn error so there is no dangling timer.

Relates to #35 (onWillSaveTextDocument timeout errors).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants