fix(hub): mark PTY session status on exit, terminate and restart - #148
Open
dvcolomban wants to merge 1 commit into
Open
fix(hub): mark PTY session status on exit, terminate and restart#148dvcolomban wants to merge 1 commit into
dvcolomban wants to merge 1 commit into
Conversation
startPtySession's proc.onExit only closed the stream, leaving status frozen at 'running' forever — unlike startChildProcess, which already marks 'stopped'/'error'. Downstream consumers relying on status to know a PTY session ended (e.g. a dock watching terminal:session:updated) never see the transition.
✅ Deploy Preview for devfra ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
There was a problem hiding this comment.
Pull request overview
Aligns PTY session lifecycle reporting in @devframes/hub with the existing child-process session behavior by ensuring PTY sessions update their status and emit session-update events when the underlying process exits, is terminated, or is restarted.
Changes:
- Added an in-place
markStatus()helper instartPtySession()to keepsession.statussynchronized with PTY process lifecycle and emitterminal:session:updated. - Updated the PTY
onExithandler to mark sessions as'stopped'on clean/signalled exit and'error'on unsignalled non-zero exit. - Added a dedicated PTY status lifecycle test suite covering exit, non-zero exit, terminate, restart, and restart-after-exit behavior.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.
| File | Description |
|---|---|
| packages/hub/src/node/host-terminals.ts | Updates PTY session exit/terminate/restart handling to mutate status and emit terminal:session:updated consistently with child-process sessions. |
| packages/hub/src/node/tests/host-terminals.test.ts | Adds regression tests to validate PTY status transitions and update emission across lifecycle events. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
startPtySession'sproc.onExitonly closed the output stream — it never touched the registered session'sstatus, so a PTY session stayed'running'forever after its process was gone.This mirrors what
startChildProcessalready does, so the two spawn helpers now expose the same lifecycle to consumers:'stopped'on a clean or signalled exit,'error'on an unsignalled non-zero exit (zigpty reportssignal: 0when no signal was involved), matchingstartChildProcess'stypeof code === 'number' && code !== 0classification.terminate()— mark'stopped', so a deliberate kill doesn't read as a crash.restart()— mark'running', matchingstartChildProcess's restart.This one is symmetry rather than an observable fix: the
streamClosedearly-return means status is already'running'whenever the body runs, somarkStatusde-dupes it.It removes the implicit dependency on
streamClosedandstatusstaying in lockstep — the same coupling that let the exit bug hide.Status is mutated in place through a
markStatushelper that emitsterminal:session:updated, copied fromstartChildProcess— consistent withupdate()'sObject.assignsemantics, and with consumers that readstatusoff the live session object (e.g.plugins/terminals's manager maps'stopped'→'exited'at list time).What it fixes
Anything relying on
statusto learn that a PTY session ended never saw the transition — a dock watchingterminal:session:updated, the hub's debounceddevframe:terminals:updatedbroadcast, and the terminals plugin's aggregated view of foreign sessions, which all kept rendering a dead shell as running until something else forced a refresh.Tests
Five cases in
host-terminals.test.ts, gated onhasNativelike the surrounding PTY tests (0 skipped locally, so all of them genuinely ran):'stopped'+ an emitted update,'error',terminate()→'stopped'rather than'error',restart()→ back to'running', andrestart()after exit staying'stopped'(pinning thestreamClosedno-op).pnpm lint && pnpm test && pnpm typecheck && pnpm buildall pass.Note for maintainers
In both helpers the exit handler is registered before
sessionis assigned —pty = spawnPty()precedes the session literal, ascp = createChildProcess()does instartChildProcess— so a synchronous exit delivery would throwReferenceError: Cannot access 'session' before initializationfrom inside the callback.Unreachable today (both zigpty and
child_processdefer exit to the event loop), and pre-existing rather than introduced here, so I kept the existing shape rather than widen the diff.If you'd like it closed off, constructing the session literal before the spawn is behaviour-neutral in both methods (the closures capture the
pty/cpvariables, not their values), happy to add that here or in a follow-up.