Skip to content

Commit

Permalink
Fix order and robustness of CTRL_*_EVENTs
Browse files Browse the repository at this point in the history
  • Loading branch information
lhecker committed Nov 21, 2024
1 parent 282670a commit 0f8e020
Show file tree
Hide file tree
Showing 2 changed files with 35 additions and 22 deletions.
49 changes: 28 additions & 21 deletions src/host/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -321,28 +321,35 @@ void ProcessCtrlEvents()
return;
}

auto Status = STATUS_SUCCESS;
const auto ctrl = ServiceLocator::LocateConsoleControl();

for (const auto& r : termRecords)
{
/*
* Status will be non-successful if a process attached to this console
* vetoes shutdown. In that case, we don't want to try to kill any more
* processes, but we do need to make sure we continue looping so we
* can close any remaining process handles. The exception is if the
* process is inaccessible, such that we can't even open a handle for
* query. In this case, use best effort to send the close event but
* ignore any errors.
*/
if (SUCCEEDED_NTSTATUS(Status))
{
Status = ServiceLocator::LocateConsoleControl()
->EndTask(r.dwProcessID,
EventType,
CtrlFlags);
if (!r.hProcess)
{
Status = STATUS_SUCCESS;
}
}
// Older versions of Windows would do various things at this point:
// * XP: Pops up a "Windows can't end this program" dialog for every already-dead process.
// * Vista - Win 7: Simply skips over already-dead processes.
// * Win 8 - Windows 11 26100: Aborts on an already-dead process (you have to WM_CLOSE conhost multiple times).
//
// That last period had the following comment:
// Status will be non-successful if a process attached to this console
// vetoes shutdown. In that case, we don't want to try to kill any more
// processes, but we do need to make sure we continue looping so we
// can close any remaining process handles. The exception is if the
// process is inaccessible, such that we can't even open a handle for
// query. In this case, use best effort to send the close event but
// ignore any errors.
//
// The corresponding logic worked like this:
// if (FAILED(EndTask(...)) && r.hProcess) {
// break;
// }
//
// That logic was removed around the Windows 11 26100 time frame, because CRSS
// (which handles EndTask) now waits 5s and then force-kills the process for us.
// Going back to the old behavior then should make shutdown a lot more robust.
// The bad news is that EndTask() returns STATUS_UNSUCCESSFUL no matter whether
// the process was already dead, or if the request actually failed for some reason.
// Hopefully there aren't any regressions, but we can't know without trying.
LOG_IF_NTSTATUS_FAILED(ctrl->EndTask(r.dwProcessID, EventType, CtrlFlags));
}
}
8 changes: 7 additions & 1 deletion src/server/ProcessList.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -211,9 +211,15 @@ ConsoleProcessHandle* ConsoleProcessList::GetOldestProcess() const
{
termRecords.clear();

// The caller (ProcessCtrlEvents) expects them in newest-to-oldest order,
// because that's how Windows has historically always dispatched these events.
auto it = _processes.crbegin();
const auto end = _processes.crend();

// Dig through known processes looking for a match
for (const auto& p : _processes)
for (; it != end; ++it)
{
const auto p = *it;
// If no limit was specified OR if we have a match, generate a new termination record.
if (!dwLimitingProcessId ||
p->_ulProcessGroupId == dwLimitingProcessId)
Expand Down

1 comment on commit 0f8e020

@github-actions
Copy link

Choose a reason for hiding this comment

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

@check-spelling-bot Report

🔴 Please review

See the 📜action log or 📝 job summary for details.

Unrecognized words (1)

CRSS

Previously acknowledged words that are now absent barbaz Ralph stb 🫥
To accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the [email protected]:microsoft/terminal.git repository
on the dev/lhecker/15373-ctrl-close-fix branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/v0.0.22/apply.pl' |
perl - 'https://github.com/microsoft/terminal/actions/runs/11957644521/attempts/1'
Available 📚 dictionaries could cover words (expected and unrecognized) not in the 📘 dictionary

This includes both expected items (2229) from .github/actions/spelling/expect/alphabet.txt
.github/actions/spelling/expect/expect.txt
.github/actions/spelling/expect/web.txt and unrecognized words (1)

Dictionary Entries Covers Uniquely
cspell:cpp/src/lang-jargon.txt 11 1 1
cspell:swift/src/swift.txt 53 1 1
cspell:gaming-terms/dict/gaming-terms.txt 59 1 1
cspell:monkeyc/src/monkeyc_keywords.txt 123 1 1
cspell:cryptocurrencies/cryptocurrencies.txt 125 1 1

Consider adding them (in .github/workflows/spelling2.yml) for uses: check-spelling/[email protected] in its with:

      with:
        extra_dictionaries:
          cspell:cpp/src/lang-jargon.txt
          cspell:swift/src/swift.txt
          cspell:gaming-terms/dict/gaming-terms.txt
          cspell:monkeyc/src/monkeyc_keywords.txt
          cspell:cryptocurrencies/cryptocurrencies.txt

To stop checking additional dictionaries, add (in .github/workflows/spelling2.yml) for uses: check-spelling/[email protected] in its with:

check_extra_dictionaries: ''
Errors (1)

See the 📜action log or 📝 job summary for details.

❌ Errors Count
❌ ignored-expect-variant 6

See ❌ Event descriptions for more information.

✏️ Contributor please read this

By default the command suggestion will generate a file named based on your commit. That's generally ok as long as you add the file to your commit. Someone can reorganize it later.

If the listed items are:

  • ... misspelled, then please correct them instead of using the command.
  • ... names, please add them to .github/actions/spelling/allow/names.txt.
  • ... APIs, you can add them to a file in .github/actions/spelling/allow/.
  • ... just things you're using, please add them to an appropriate file in .github/actions/spelling/expect/.
  • ... tokens you only need in one place and shouldn't generally be used, you can add an item in an appropriate file in .github/actions/spelling/patterns/.

See the README.md in each directory for more information.

🔬 You can test your commits without appending to a PR by creating a new branch with that extra change and pushing it to your fork. The check-spelling action will run in response to your push -- it doesn't require an open pull request. By using such a branch, you can limit the number of typos your peers see you make. 😉

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

Please sign in to comment.