Skip to content

Restore terminal cursor visibility on exit in collect-linux#5707

Open
Copilot wants to merge 7 commits intomainfrom
copilot/fix-terminal-cursor-visibility
Open

Restore terminal cursor visibility on exit in collect-linux#5707
Copilot wants to merge 7 commits intomainfrom
copilot/fix-terminal-cursor-visibility

Conversation

Copy link
Contributor

Copilot AI commented Feb 7, 2026

Fix terminal cursor visibility in dotnet-trace collect-linux

Problem

The dotnet-trace collect-linux command hides the terminal cursor during operation but fails to restore it on exit, leaving users with an invisible cursor that requires manual restoration via tput cnorm or reset.

Solution

Added cursor visibility restoration in the finally block with proper state tracking to ensure the cursor is restored correctly on all exit paths.

Changes Made

  1. CollectLinuxCommand.cs: Enhanced cursor visibility handling

    • Cache original cursor visibility state before hiding
    • Only hide cursor when !Console.IsOutputRedirected
    • Restore original cursor state in finally block only if changed
    • Prevents changing cursor on early return paths (e.g., --probe)
  2. CollectLinuxCommandFunctionalTests.cs: Updated and improved tests

    • Renamed test to CollectLinuxCommand_DoesNotChangeCursorVisibility_WhenOutputIsRedirected to better reflect behavior
    • Converted to theory with InlineData to test both true and false initial cursor states
    • Verifies cursor remains in original state when output is redirected
    • Removed brittle line number reference from comment

Testing

  • All 32 CollectLinuxCommand tests passing (31 passed, 1 skipped for platform)
    • Theory now runs twice: once with cursor initially visible, once with cursor initially hidden
  • All cursor visibility tests passing
  • No regressions in existing functionality

Code Changes

bool cursorVisibilityChanged = false;
bool originalCursorVisible = false;

// Only hide cursor if output is not redirected
if (!Console.IsOutputRedirected)
{
    originalCursorVisible = Console.CursorVisible;
    Console.CursorVisible = false;
    cursorVisibilityChanged = true;
}

// In finally block:
if (cursorVisibilityChanged)
{
    Console.CursorVisible = originalCursorVisible;
}
Original prompt

This section details on the original issue you should resolve

<issue_title>dotnet-trace collect-linux leaves terminal cursor hidden after tracing completes</issue_title>
<issue_description>### Description

After dotnet-trace collect-linux finishes collecting a trace and exits, the terminal cursor remains hidden. The cursor is not restored to its visible state on exit, leaving the user with an invisible cursor in their terminal session.

Steps to Reproduce

  1. Open a terminal session.
  2. Run dotnet-trace collect-linux -p <pid> (or any valid collect-linux invocation).
  3. Wait for trace collection to complete, or stop it with Ctrl+C / Enter.
  4. Observe that the terminal cursor is no longer visible after the tool exits.
  5. The terminal is still functional (typing works), but the cursor is invisible.

Expected Behavior

After dotnet-trace collect-linux exits — whether through normal completion, user-initiated stop, or signal — the terminal cursor should be restored to its visible state. The tool should ensure terminal state cleanup happens on all exit paths.

Actual Behavior

The cursor remains hidden after the tool exits. Users must manually restore it by running tput cnorm or reset to get their cursor back.

Additional Context

  • The tool likely hides the cursor (e.g., via ANSI escape \e[?25l) during collection for TUI/progress rendering but does not emit the corresponding show-cursor sequence (\e[?25h) on exit.
  • The fix should ensure cursor restoration on all exit paths: normal exit, SIGINT, SIGTERM, and any error/panic paths.
  • Consider using a cleanup guard or defer/finally pattern to guarantee terminal state is restored regardless of how the tool exits.</issue_description>

Comments on the Issue (you are @copilot in this section)


💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.

Copilot AI and others added 4 commits February 7, 2026 08:45
- Add finally block to restore cursor visibility on all exit paths
- Check IsOutputRedirected before restoring cursor
- Add unit tests to verify cursor restoration behavior

Co-authored-by: hoyosjs <19413848+hoyosjs@users.noreply.github.com>
Remove manual cursor state manipulation in test to properly verify
that the finally block respects IsOutputRedirected flag

Co-authored-by: hoyosjs <19413848+hoyosjs@users.noreply.github.com>
Co-authored-by: hoyosjs <19413848+hoyosjs@users.noreply.github.com>
Copilot AI changed the title [WIP] Fix hidden terminal cursor after dotnet-trace collect-linux Restore terminal cursor visibility on exit in collect-linux Feb 7, 2026
Copilot AI requested a review from hoyosjs February 7, 2026 08:51
@hoyosjs
Copy link
Member

hoyosjs commented Feb 7, 2026

I tested and this seems to be working correctly.

@hoyosjs hoyosjs marked this pull request as ready for review February 7, 2026 09:40
@hoyosjs hoyosjs requested a review from a team as a code owner February 7, 2026 09:40
Copilot AI review requested due to automatic review settings February 7, 2026 09:40
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes terminal state cleanup for dotnet-trace collect-linux by ensuring the cursor is restored after trace collection, and adds functional tests around cursor visibility behavior.

Changes:

  • Restore cursor visibility in CollectLinuxCommandHandler.CollectLinux via a finally block.
  • Add functional tests for cursor visibility on success, error, and redirected-output scenarios.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 4 comments.

File Description
src/Tools/dotnet-trace/CommandLine/Commands/CollectLinuxCommand.cs Adds cursor restoration logic in finally for collect-linux execution paths.
src/tests/dotnet-trace/CollectLinuxCommandFunctionalTests.cs Adds tests intended to validate cursor visibility restoration behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

- Check IsOutputRedirected before hiding cursor
- Cache original cursor visibility state
- Restore original state only if changed
- Update test to verify cursor unchanged when redirected

Co-authored-by: hoyosjs <19413848+hoyosjs@users.noreply.github.com>
@@ -257,14 +257,14 @@ public void CollectLinuxCommand_RestoresCursorVisibility_OnError()
public void CollectLinuxCommand_DoesNotRestoreCursor_WhenOutputIsRedirected()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot the test name suggests that the cursor would be hidden and remain hidden when the output is redirected. Could it be renamed to CollectLinuxCommand_DoesNotChangeCursorVisibility_WhenOutputIsRedirected.

Can this be a theory taking in true/false as the original cursor's visibility

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be nice to have a test validating that the cursor is still visible during tracing, but given that it's currently a synchronous method, it doesn't seem reasonably easily testable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in commit ecb67f1. Renamed the test to CollectLinuxCommand_DoesNotChangeCursorVisibility_WhenOutputIsRedirected and converted it to a theory with InlineData(true) and InlineData(false) to test both initial cursor visibility states.

- Rename test to CollectLinuxCommand_DoesNotChangeCursorVisibility_WhenOutputIsRedirected
- Convert from Fact to Theory with InlineData for true/false cursor states
- Test now validates both initial cursor visibility states

Co-authored-by: mdh1418 <16830051+mdh1418@users.noreply.github.com>
Copilot AI requested a review from mdh1418 February 8, 2026 04:34
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.

dotnet-trace collect-linux leaves terminal cursor hidden after tracing completes

3 participants