Skip to content

refactor(logger): Restore cursor on ui5 serve termination - #1475

Merged
RandomByte merged 2 commits into
mainfrom
refactor/interactive-console-cursor-restore
Jul 24, 2026
Merged

refactor(logger): Restore cursor on ui5 serve termination#1475
RandomByte merged 2 commits into
mainfrom
refactor/interactive-console-cursor-restore

Conversation

@RandomByte

@RandomByte RandomByte commented Jul 23, 2026

Copy link
Copy Markdown
Member

The log-update package hides the terminal cursor on every render and only shows it again in its own done(), which InteractiveConsole calls from disable(). On CTRL+C the process is signal-terminated without disable() ever running, so the cursor stays hidden in the user's shell. The restore-cursor safety net (a bare \x1b[?25h with no newline) is also swallowed: the stderr write interceptor buffers non-newline-terminated writes into partial and only flushes them in disable().

Register a handler for SIGINT/SIGTERM/SIGHUP/SIGBREAK (and an exit catch-all) in enable(), removed in disable(). Each signal handler tears the live region down via disable(), then re-raises the signal with process.kill(process.pid, signal) rather than calling process.exit(). Re-raising lets the cooperating handlers in profile.js and ProjectBuilder still run their async cleanup, and lets the default disposition set the 128+n exit code. disable() removes the handlers before re-raise so the re-sent signal reaches the default disposition instead of looping.

disable() now also writes the show-cursor escape explicitly to its own stream, after uninstalling the interceptor. log-update's done() targets the real process.stderr and is gated on isTTY, so it can be a no-op; the explicit write restores the cursor regardless and is observable in tests.

log-update hides the terminal cursor on every render and only shows it
again in its own done(), which InteractiveConsole calls from disable().
On CTRL+C the process is signal-terminated without disable() ever
running, so the cursor stays hidden in the user's shell. The
restore-cursor safety net (a bare "\x1b[?25h" with no newline) is also
swallowed: the stderr write interceptor buffers non-newline-terminated
writes into `partial` and only flushes them in disable().

Register a handler for SIGINT/SIGTERM/SIGHUP/SIGBREAK (and an `exit`
catch-all) in enable(), removed in disable(). Each signal handler tears
the live region down via disable(), then re-raises the signal with
process.kill(process.pid, signal) rather than calling process.exit().
Re-raising lets the cooperating handlers in profile.js and ProjectBuilder
still run their async cleanup, and lets the default disposition set the
128+n exit code. disable() removes the handlers before re-raise so the
re-sent signal reaches the default disposition instead of looping.

disable() now also writes the show-cursor escape explicitly to its own
stream, after uninstalling the interceptor. log-update's done() targets
the real process.stderr and is gated on isTTY, so it can be a no-op; the
explicit write restores the cursor regardless and is observable in tests.
@RandomByte
RandomByte marked this pull request as ready for review July 23, 2026 15:02
@RandomByte
RandomByte requested a review from a team July 23, 2026 15:02
Comment thread packages/logger/lib/writers/InteractiveConsole.js
A second enable() without an intervening disable() overwrote every
#signalHandlers map entry with fresh closures, stranding the first set
of handlers on process. #deregisterSignalHandlers() iterates the map, so
it could only detach the latest set, leaking the originals.

Guard #registerSignalHandlers() on the map already being populated and
return early, mirroring how disable() guards on #stopped. Registration
and deregistration happen as a unit, so a single check covers all
signals.
@RandomByte
RandomByte force-pushed the refactor/interactive-console-cursor-restore branch from 902fc65 to 55f5546 Compare July 24, 2026 09:27
@RandomByte
RandomByte merged commit 5b011d2 into main Jul 24, 2026
60 checks passed
@RandomByte
RandomByte deleted the refactor/interactive-console-cursor-restore branch July 24, 2026 14:28
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