Skip to content

Fixes #4920. Re-enter RunLoop when End is cancelled by IsRunningChanging#4921

Merged
YourRobotOverlord merged 4 commits intogui-cs:developfrom
YourRobotOverlord:fix/stop-requested-not-reset-on-cancel
Apr 10, 2026
Merged

Fixes #4920. Re-enter RunLoop when End is cancelled by IsRunningChanging#4921
YourRobotOverlord merged 4 commits intogui-cs:developfrom
YourRobotOverlord:fix/stop-requested-not-reset-on-cancel

Conversation

@YourRobotOverlord
Copy link
Copy Markdown
Collaborator

@YourRobotOverlord YourRobotOverlord commented Apr 10, 2026

Fixes #4920.

Problem

See the linked issue. When OnIsRunningChanging (or an IsRunningChanging event handler) vetoes a stop, ApplicationImpl.Run() returned early leaving the runnable with IsRunning=true, StopRequested=true, and no event loop active — a freeze or crash.

Fix

In ApplicationImpl.Run(), wrap the RunLoop / End block in a while(true) loop and only break when End() succeeds (i.e. runnable.IsRunning == false). When End is cancelled, reset StopRequested=false and re-enter RunLoop:

// BEFORE
try
{
    RunLoop(runnable, errorHandler);
}
finally
{
    End(token);
}

// AFTER
while (true)
{
    try
    {
        RunLoop(runnable, errorHandler);
    }
    finally
    {
        End(token);
    }

    if (!runnable.IsRunning)
        break;

    // End was vetoed — reset StopRequested so RunLoop can re-enter correctly
    runnable.StopRequested = false;
}

Why This Is Safe

Scenario Before After
Normal stop ✅ works ✅ same — IsRunning becomes false after End, loop breaks
Exception in RunLoop End runs in finally, exception propagates ✅ same
Stop vetoed by IsRunningChanging Run() returns early; runnable dead RunLoop re-entered; runnable stays interactive

Changes

File Change
Terminal.Gui/App/ApplicationImpl.Run.cs Wrap try/finally in while(true) loop
Tests/UnitTestsParallelizable/Application/ApplicationImplTests.cs Regression test Run_WhenStopCancelledByIsRunningChanging_RunLoopResumes
Examples/UICatalog/Scenarios/IsRunningChangingCancelDemo.cs New UICatalog scenario demonstrating the OnIsRunningChanging veto pattern

YourRobotOverlord and others added 2 commits April 9, 2026 22:07
When an IsRunningChanging handler vetoed a stop (e.g. 'Are you sure?'
pattern), End() returned early but Run() also returned - leaving
IsRunning=true, StopRequested=true, and no event loop running, causing
an application freeze.

Fix: wrap the try/finally in ApplicationImpl.Run() in a while(true) loop.
After End() returns, check runnable.IsRunning:
- false -> End succeeded, break (no behaviour change)
- true  -> End was cancelled, reset StopRequested=false and re-enter RunLoop

Also adds:
- UICatalog scenario CancelStopDemo to reproduce the freeze visually
- Regression test Run_WhenStopCancelledByIsRunningChanging_RunLoopResumes

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…e/description

- Rename file CancelStopDemo.cs → IsRunningChangingCancelDemo.cs
- Rename class CancelStopDemo → IsRunningChangingCancelDemo
- ScenarioMetadata name: 'IsRunningChanging Cancel Demo'
- ScenarioMetadata description: 'Demonstrates vetoing a stop by overriding OnIsRunningChanging — the dialog stays interactive after the user chooses Stay'
- Update XML doc comments to lead with OnIsRunningChanging rather than 'cancel stop pattern'

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@YourRobotOverlord YourRobotOverlord requested a review from tig as a code owner April 10, 2026 04:35
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Collaborator

@tig tig left a comment

Choose a reason for hiding this comment

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

Lovely! See my request.

Comment thread Examples/UICatalog/Scenarios/IsRunningChangingCancelDemo.cs Outdated
Unit tests provide sufficient coverage; the UICatalog scenario is not needed.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@YourRobotOverlord YourRobotOverlord requested a review from tig April 10, 2026 15:14
@YourRobotOverlord YourRobotOverlord merged commit 10cf766 into gui-cs:develop Apr 10, 2026
11 checks passed
@YourRobotOverlord YourRobotOverlord deleted the fix/stop-requested-not-reset-on-cancel branch April 10, 2026 20:04
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.

StopRequested not reset when IsRunningChanging cancels a stop, causing freeze/crash

2 participants