Windows Terminal Window Does Not Send EVENT_OBJECT_DESTROY On Close #21744

Open
opened 2026-01-31 07:53:41 +00:00 by claunia · 6 comments
Owner

Originally created by @LGUG2Z on GitHub (May 22, 2024).

Originally assigned to: @lhecker on GitHub.

Windows Terminal version

1.19.11213.0

Windows build number

10.0.22631.0

Other Software

No response

Steps to reproduce

Open a single instance of Windows terminal on the desktop. Close that instance of Windows Terminal. EVENT_OBJECT_DESTROY is not emitted.

Expected Behavior

EVENT_OBJECT_DESTROY should be emitted when the Windows Terminal window is closed by the window handle that the user has just interacted with.

Actual Behavior

EVENT_OBJECT_DESTROY is not emitted for the Windows Terminal window that was closed.

When opening Windows Terminal, EVENT_SYSTEM_FOREGROUND is emitted, and the window handle of the actual window that I as the user interact with is the log example below is 658858:

2024-05-22T01:39:16.367526Z  INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 658858 })}: komorebi::process_event: processed: (hwnd: 658858, title: PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS)

When I close the window, sometimes an EVENT_OBJECT_HIDE is emitted, but it is emitted for a completely separate window handle (920252):

2024-05-22T01:39:18.051931Z DEBUG process_event{event=Hide(ObjectHide, Window { hwnd: 920252 })}:should_manage{self=Window { hwnd: 920252 } event=Some(Hide(ObjectHide, Window { hwnd: 920252 }))}: komorebi::window: ignoring (exe: WindowsTerminal.exe, title: DesktopWindowXamlSource, event: Hide (WinEvent: ObjectHide, Window: (hwnd: 920252)))
Originally created by @LGUG2Z on GitHub (May 22, 2024). Originally assigned to: @lhecker on GitHub. ### Windows Terminal version 1.19.11213.0 ### Windows build number 10.0.22631.0 ### Other Software _No response_ ### Steps to reproduce Open a single instance of Windows terminal on the desktop. Close that instance of Windows Terminal. `EVENT_OBJECT_DESTROY` is not emitted. ### Expected Behavior `EVENT_OBJECT_DESTROY` should be emitted when the Windows Terminal window is closed by the window handle that the user has just interacted with. ### Actual Behavior `EVENT_OBJECT_DESTROY` is not emitted for the Windows Terminal window that was closed. When opening Windows Terminal, `EVENT_SYSTEM_FOREGROUND` is emitted, and the window handle of the actual window that I as the user interact with is the log example below is `658858`: ``` 2024-05-22T01:39:16.367526Z INFO process_event{event=FocusChange(SystemForeground, Window { hwnd: 658858 })}: komorebi::process_event: processed: (hwnd: 658858, title: PowerShell, exe: WindowsTerminal.exe, class: CASCADIA_HOSTING_WINDOW_CLASS) ``` When I close the window, _sometimes_ an `EVENT_OBJECT_HIDE` is emitted, but it is emitted for a completely separate window handle (`920252`): ``` 2024-05-22T01:39:18.051931Z DEBUG process_event{event=Hide(ObjectHide, Window { hwnd: 920252 })}:should_manage{self=Window { hwnd: 920252 } event=Some(Hide(ObjectHide, Window { hwnd: 920252 }))}: komorebi::window: ignoring (exe: WindowsTerminal.exe, title: DesktopWindowXamlSource, event: Hide (WinEvent: ObjectHide, Window: (hwnd: 920252))) ```
claunia added the Needs-TriageIssue-BugNeeds-Attention labels 2026-01-31 07:53:41 +00:00
Author
Owner

@lhecker commented on GitHub (May 27, 2024):

I'm somewhat surprised that the OS doesn't do that for us. We use TerminateProcess on exit to work around issues in WinUI (in particular on Windows 10). It's a simple and effective solution.

While I can see how we should try to emit these events on exit, I'm not sure whether that would help your project at all. A lot of applications, and not just Windows Terminal, use TerminateProcess and I wonder if the same issue will happen if you kill a process with the task manager. Since TerminateProcess is an entirely valid way to exit an application I'm not sure whether calling Windows Terminal buggy is fair.
But in any case, I suppose you'd need to make your window manager robust against sudden process exits independent of whether we address this issue or not.

@lhecker commented on GitHub (May 27, 2024): I'm somewhat surprised that the OS doesn't do that for us. We use `TerminateProcess` on exit to work around issues in WinUI (in particular on Windows 10). It's a simple and effective solution. While I can see how we should try to emit these events on exit, I'm not sure whether that would help your project at all. A lot of applications, and not just Windows Terminal, use `TerminateProcess` and I wonder if the same issue will happen if you kill a process with the task manager. Since `TerminateProcess` is an entirely valid way to exit an application I'm not sure whether calling Windows Terminal buggy is fair. But in any case, I suppose you'd need to make your window manager robust against sudden process exits independent of whether we address this issue or not.
Author
Owner

@LGUG2Z commented on GitHub (May 27, 2024):

Updates have already been made on our side to protect against any other applications which might exhibit this kind of non-standard WinEvent behaviour in the future (referenced commit above).

I wonder if the same issue will happen if you kill a process with the task manager

I can confirm this is not the case; applications killed from the Task Manager send EVENT_OBJECT_DESTROY.

A lot of applications, and not just Windows Terminal, use TerminateProcess

komorebi users are pretty quick and vocal to report issues like these, and with tens of thousands of users across a variety of professions using a breadth of both modern and legacy applications, Windows Terminal is the only application which has been reported to exhibit this behaviour.

If and when there are more examples from other applications I will be happy to share them, but for now, if 99% of other applications windows are doing the right thing (sending the appropriate WinEvent when they are destroyed), I think it's worth trying to bring WT into conformance with the expected application behaviour in the Windows ecosystem.

@LGUG2Z commented on GitHub (May 27, 2024): Updates have already been made on our side to protect against any other applications which might exhibit this kind of non-standard `WinEvent` behaviour in the future (referenced commit above). > I wonder if the same issue will happen if you kill a process with the task manager I can confirm this is not the case; applications killed from the Task Manager send `EVENT_OBJECT_DESTROY`. > A lot of applications, and not just Windows Terminal, use `TerminateProcess` `komorebi` users are pretty quick and vocal to report issues like these, and with tens of thousands of users across a variety of professions using a breadth of both modern and legacy applications, Windows Terminal is the only application which has been reported to exhibit this behaviour. If and when there are more examples from other applications I will be happy to share them, but for now, if 99% of other applications windows are doing the right thing (sending the appropriate `WinEvent` when they are destroyed), I think it's worth trying to bring WT into conformance with the expected application behaviour in the Windows ecosystem.
Author
Owner

@lhecker commented on GitHub (May 27, 2024):

I've hacked this C++ snippet together as a test case for this issue: https://gist.github.com/lhecker/82b029643e9f9ccf15304a623093880b
For any given application name, it records a set of HWNDs. They're added to the set on EVENT_OBJECT_CREATE and removed on EVENT_OBJECT_DESTROY. Currently, when opening/closing the window the counter for WindowsTerminal.exe will constantly increase.

However, I'm doing something wrong in that code, because the same thing happens for VS Code and other applications:

https://github.com/microsoft/terminal/assets/2256941/348d3489-c5ec-47bf-ac27-07bdd39d19fd

Since it happens with pretty much all applications, I must be doing something wrong but I can't figure out what. @LGUG2Z I don't mean to bother you unnecessarily, but if you can spot any flaws with what I described above, or any flaws in my code, please let me know. 🙂

@lhecker commented on GitHub (May 27, 2024): I've hacked this C++ snippet together as a test case for this issue: https://gist.github.com/lhecker/82b029643e9f9ccf15304a623093880b For any given application name, it records a set of HWNDs. They're added to the set on `EVENT_OBJECT_CREATE` and removed on `EVENT_OBJECT_DESTROY`. Currently, when opening/closing the window the counter for WindowsTerminal.exe will constantly increase. However, I'm doing something wrong in that code, because the same thing happens for VS Code and other applications: https://github.com/microsoft/terminal/assets/2256941/348d3489-c5ec-47bf-ac27-07bdd39d19fd Since it happens with pretty much all applications, I must be doing something wrong but I can't figure out what. @LGUG2Z I don't mean to bother you unnecessarily, but if you can spot any flaws with what I described above, or any flaws in my code, please let me know. 🙂
Author
Owner

@lhecker commented on GitHub (May 27, 2024):

Just after writing that comment, I finally figured out the first mistake I made! Apparently, when a EVENT_OBJECT_DESTROY is received, OpenProcess may not work anymore. In my first version I did an early return in that case.

I've now changed the code to instead search through all windows and that gets VS Code down to just 0 to 1 HWND leaks per launch. But that's the same amount as for Windows Terminal. Weird. Am I checking some of the callback parameters incorrectly? 🤔

@lhecker commented on GitHub (May 27, 2024): Just after writing that comment, I finally figured out the first mistake I made! Apparently, when a `EVENT_OBJECT_DESTROY` is received, `OpenProcess` may not work anymore. In my first version I did an early return in that case. I've now changed the code to instead search through all windows and that gets VS Code down to just 0 to 1 HWND leaks per launch. But that's the same amount as for Windows Terminal. Weird. Am I checking some of the callback parameters incorrectly? 🤔
Author
Owner

@LGUG2Z commented on GitHub (May 27, 2024):

Unfortunately I'm not well versed enough with CPP to offer much meaningful insight, but I created something similar using windows-rs here: https://gist.github.com/LGUG2Z/da57d4f1fb294266e3793348b149fb79

[src\main.rs:126:5] state = {
    "C:\\Windows\\explorer.exe": 3,
    "C:\\Program Files\\WindowsApps\\Microsoft.WindowsTerminal_1.19.11213.0_x64__8wekyb3d8bbwe\\WindowsTerminal.exe": 2,
    "C:\\Windows\\SystemApps\\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\\StartMenuExperienceHost.exe": 5,
}

I'm tracking the state in a hashmap keyed by the exe path, incrementing by 1 whenever a create event comes through, decrementing by 1 whenever a destroy event comes through, and removing from the map when we drop to 0.

For when OpenProcess calls might fail, there is another hashmap keyed with the HWND to look up the exe path if the API call fails.

With this I can see that there are a few lingering create events between opening and closing instances of WT that don't have corresponding destroy events, and I'm betting these are for the visible window that interaction happens with 🤔

@LGUG2Z commented on GitHub (May 27, 2024): Unfortunately I'm not well versed enough with CPP to offer much meaningful insight, but I created something similar using `windows-rs` here: https://gist.github.com/LGUG2Z/da57d4f1fb294266e3793348b149fb79 ``` [src\main.rs:126:5] state = { "C:\\Windows\\explorer.exe": 3, "C:\\Program Files\\WindowsApps\\Microsoft.WindowsTerminal_1.19.11213.0_x64__8wekyb3d8bbwe\\WindowsTerminal.exe": 2, "C:\\Windows\\SystemApps\\Microsoft.Windows.StartMenuExperienceHost_cw5n1h2txyewy\\StartMenuExperienceHost.exe": 5, } ``` I'm tracking the state in a hashmap keyed by the exe path, incrementing by 1 whenever a create event comes through, decrementing by 1 whenever a destroy event comes through, and removing from the map when we drop to 0. For when OpenProcess calls might fail, there is another hashmap keyed with the HWND to look up the exe path if the API call fails. With this I can see that there are a few lingering create events between opening and closing instances of WT that don't have corresponding destroy events, and I'm betting these are for the visible window that interaction happens with 🤔
Author
Owner

@zadjii-msft commented on GitHub (Jun 12, 2024):

Thoughts:

  • Is this just a XAML islands thing? I think PerceptionSimulationInput (or something like that) in system32 is also XAML islands, but this might be gone in certain win11 builds.
  • Is this a RuntimeBroker thing? maybe if we're the defterm, the monarch process is still running?
  • Maybe the tray icon is still present (but not cleaned up cause {{bug number here}}, and that's why we're not having that event emitted?
  • Does this repro with the default terminal settings? allowHeadless, minimizeToNotificationArea, and _quake mode come to mind

we honestly don't know! We should find someone who does

@zadjii-msft commented on GitHub (Jun 12, 2024): Thoughts: * Is this just a XAML islands thing? I think PerceptionSimulationInput (or something like that) in system32 is also XAML islands, but this might be gone in certain win11 builds. * Is this a RuntimeBroker thing? maybe if we're the defterm, the monarch process is still running? * Maybe the tray icon is still present (but not cleaned up cause {{bug number here}}, and that's why we're not having that event emitted? * Does this repro with the default terminal settings? `allowHeadless`, `minimizeToNotificationArea`, and `_quake` mode come to mind we honestly don't know! We should find someone who does
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/terminal#21744