Skip to content

[1.22] Fix teardown when 'allowHeadless' is enabled #18869

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged

Conversation

carlos-zamora
Copy link
Member

Summary of the Pull Request

Fixes a bug where Monarch::_peasants would not be updated when the last window was closed and compatibility.allowHeadless was enabled.

Detailed Description of the Pull Request / Additional comments

The bug was originally caused by Monarch::_peasants still holding on to a reference to itself in the list. Normally, a Peasant was removed from the list via the WindowManager::SignalClose() (aka Monarch::SignalClose()) function. However, AppHost::_CloseRequested() would omit that call when the last window was closing.

Normally, that makes sense. It's the last window, so let's call AppHost::_quit() --> WindowManager::QuitAll() --> Monarch::QuitAll(), where we just call Peasant::Quit() on all the peasants and the monarch and we call it a day. Everything should be cleaned up and if we need a new session, we'll create a new Monarch anyways.

Problem is, when compatibility.allowHeadless is enabled, the WindowEmperor doesn't actually close! We want the WindowEmperor to stick around because that's the "headless" part we're allowing. See WindowEmperor::_decrementWindowCount():

void WindowEmperor::_decrementWindowCount()
{
// When we run out of windows, exit our process if and only if:
// * We're not allowed to run headless OR
// * we've explicitly been told to "quit", which should fully exit the Terminal.
const bool quitWhenLastWindowExits{ !_app.Logic().AllowHeadless() };
const bool noMoreWindows{ _windowThreadInstances.fetch_sub(1, std::memory_order_relaxed) == 1 };
if (noMoreWindows &&
(_quitting || quitWhenLastWindowExits))
{
_close();
}
}

The fix here was to avoid the QuitAll() code path mentioned above if compatibility.allowHeadless is enabled. Just treat this as a normal teardown otherwise so that the WindowEmperor creates a new Monarch when we need it.

Validation Steps Performed

✅ The scenario from the bug works:

  • enable compatibility.allowHeadless
  • set windowingBehavior to useExisting
  • Open Terminal
  • Close the only open window
  • Attempting to open Terminal again should open a new window
    ✅ when all windows are closed, we still have the background process

Closes #18827

Copy link
Member

@DHowett DHowett left a comment

Choose a reason for hiding this comment

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

Thanks! + @lhecker will you take a look too? deceptively easy fix

@DHowett
Copy link
Member

DHowett commented May 7, 2025

I think the description is subtly wrong.

We only ever have one Monarch, and it lives forever.

Copy link
Member

@lhecker lhecker left a comment

Choose a reason for hiding this comment

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

I... think? this should work. I also found the intricate dependencies in the old code somewhat confusing.

@carlos-zamora carlos-zamora merged commit c02376a into release-1.22 May 8, 2025
8 of 10 checks passed
@carlos-zamora carlos-zamora deleted the dev/cazamor/1.22/allow-headless-teardown branch May 8, 2025 18:20
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.

3 participants