Skip to content
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

Fix font preview for conhost #16324

Merged
merged 2 commits into from Nov 27, 2023
Merged

Fix font preview for conhost #16324

merged 2 commits into from Nov 27, 2023

Conversation

lhecker
Copy link
Member

@lhecker lhecker commented Nov 16, 2023

After exiting the main loop in this function the invariant
nFont <= NumberOfFonts still holds true. Additionally,
preceding this removed code is this (paraphrased):

if (nFont < NumberOfFonts) {
    RtlMoveMemory(...);
}

It ensures that the given slot nFont is always unoccupied by moving
it and all following items upwards if needed. As such, the call to
DeleteObject is always incorrect, as the slot is always "empty",
but may contain a copy of the previous occupant due to the memmove.

This regressed in 154ac2b.

Closes #16297

Validation Steps Performed

  • All fonts have a unique look in the preview panel ✅

@microsoft-github-policy-service microsoft-github-policy-service bot added Issue-Bug It either shouldn't be doing this or needs an investigation. Area-Fonts Related to the font Product-Conhost For issues in the Console codebase Severity-Blocking We won't ship a release like this! No-siree. labels Nov 16, 2023
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.

Pull request 8346069

I feel like there's a GDI object leak somewhere. While this PR introduced an overrelease, backing it out will just bring back the leak

@microsoft-github-policy-service microsoft-github-policy-service bot added the Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something label Nov 16, 2023
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.

Possibly leaking GDI objects is better than whatever it is we have today

@DHowett DHowett added this to To Cherry Pick in 1.19 Servicing Pipeline via automation Nov 16, 2023
@lhecker
Copy link
Member Author

lhecker commented Nov 16, 2023

I've tried hard to find the leak as reported initially and just couldn't spot anything even after a long time. Here's the original GDI object leak trace from the internal report:

0:004> .exr -1
ExceptionAddress: 00007ffe21252d30 (gdi32full!ReportGDILeaksToWatson)
   ExceptionCode: 803f0001
  ExceptionFlags: 00000000
NumberParameters: 4
   Parameter[0]: 00000295397d0b08
   Parameter[1]: 0009ffd8e202312f
   Parameter[2]: 00000000000007a0 <------- number of leaking objects
   Parameter[3]: 0000000000000000
0:004> !gdikdx.dbt 00000295397d0b08
dps 295397d0b18 L14

00000295`397d0b18  00007ffe`211d9fdc gdi32full!CreateFontIndirectWImpl+0x19c [clientcore\windows\core\ntgdi\client\full\object.cxx @ 2580]
00000295`397d0b20  00007ffd`dec008f7 console!AddFont+0x313 [onecore\windows\core\console\open\src\propsheet\misc.cpp @ 391]
00000295`397d0b28  00007ffd`dec013c9 console!FontEnumForV2Console+0x1b9 [onecore\windows\core\console\open\src\propsheet\misc.cpp @ 582]
00000295`397d0b30  00007ffe`211d83b9 gdi32full!EnumFontsInternalW+0x149 [clientcore\windows\core\ntgdi\client\full\font.c @ 1863]
00000295`397d0b38  00007ffe`212137fc gdi32full!EnumFontFamiliesExW+0x4c [clientcore\windows\core\ntgdi\client\full\font.c @ 1983]
00000295`397d0b40  00007ffd`dec00c6f console!DoFontEnum+0x137 [onecore\windows\core\console\open\src\propsheet\misc.cpp @ 821]
00000295`397d0b48  00007ffd`dec00ecd console!EnumerateFonts+0x219 [onecore\windows\core\console\open\src\propsheet\misc.cpp @ 1036]
00000295`397d0b50  00007ffd`debfb3ca console!FontListCreate+0xba [onecore\windows\core\console\open\src\propsheet\fontdlg.cpp @ 728]
00000295`397d0b58  00007ffd`debfb0aa console!FontDlgProc+0x43a [onecore\windows\core\console\open\src\propsheet\fontdlg.cpp @ 302]
00000295`397d0b60  00007ffe`23b85a5f user32!UserCallDlgProcCheckWow+0x20f [clientcore\windows\core\ntuser\client\clmsg.cxx @ 364]
00000295`397d0b68  00007ffe`23b84ae9 user32!DefDlgProcWorker+0xc9 [clientcore\windows\core\ntuser\client\dlgmgr.cxx @ 965]
00000295`397d0b70  00007ffe`23b849f6 user32!DefDlgProcW+0x36 [clientcore\windows\core\ntuser\client\dlgmgr.cxx @ 1491]
00000295`397d0b78  00007ffe`23b7057a user32!UserCallWinProcCheckWow+0x2ba [clientcore\windows\core\ntuser\client\clmsg.cxx @ 281]
00000295`397d0b80  00007ffe`23b6f885 user32!SendMessageWorker+0x2d5 [clientcore\windows\core\ntuser\client\clmsg.cxx @ 890]
00000295`397d0b88  00007ffe`23b87233 user32!InternalCreateDialog+0xd1f [clientcore\windows\core\ntuser\client\dlgbegin.cxx @ 1396]
00000295`397d0b90  00007ffe`23b846b7 user32!CreateDialogIndirectParamAorW+0x57 [clientcore\windows\core\ntuser\client\clres.cxx @ 930]
00000295`397d0b98  00007ffe`23b84618 user32!CreateDialogIndirectParamW+0x18 [clientcore\windows\core\ntuser\client\clres.cxx @ 898]
00000295`397d0ba0  00007ffe`0d7761d3 comctl32!_CreatePageDialog+0xc3 [shell\comctl32\v6\prpage.cpp @ 522]
00000295`397d0ba8  00007ffe`0d7760c1 comctl32!_CreatePage+0x121 [shell\comctl32\v6\prpage.cpp @ 721]
00000295`397d0bb0  00007ffe`0d778a5b comctl32!PageChange+0xe7 [shell\comctl32\v6\prsht.cpp @ 1544]

It's unlikely that the tool is incorrect, but clearly the conclusions we've drawn initially were wrong. This isn't how to fix the leak. But what other code could cause this? Apart from this function the only other culprits I can find are RemoveFace, FontPreviewWndProc, RecreateFontHandles and DestroyFonts. They all seemed correct to me.

@microsoft-github-policy-service microsoft-github-policy-service bot added Needs-Attention The core contributors need to come back around and look at this ASAP. and removed Needs-Author-Feedback The original author of the issue/PR needs to come back and respond to something labels Nov 16, 2023
Copy link
Member

@zadjii-msft zadjii-msft left a comment

Choose a reason for hiding this comment

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

Sure. I'll leave a note in the original PR that regressed this

@lhecker lhecker added AutoMerge Marked for automatic merge by the bot when requirements are met and removed Needs-Attention The core contributors need to come back around and look at this ASAP. labels Nov 21, 2023
@hussien89aa
Copy link

I do not think we can fix regression here by introducing another regression. The origin regression caused the app to crash so it was way worse than the current issue. I think you can fix it better way by finding where the GDI object address has been copied and only delete it when you no longer need it. Also can you please share with me the steps to repro the issue? i want to repro locally?

@lhecker
Copy link
Member Author

lhecker commented Nov 21, 2023

I do not think we can fix regression here by introducing another regression. The origin regression caused the app to crash so it was way worse than the current issue.

FWIW the reason the leak-fix works is because it frees the previously added handle while a new one is being added. Then, during exit, we'll free all those already freed handles again (DestroyFonts). I'm worried that this may also cause GDI to crash in the future. After all, the documentation says "After the object is deleted, the specified handle is no longer valid.".

I think you can fix it better way by finding where the GDI object address has been copied and only delete it when you no longer need it.

I'm not entirely sure I understand what you mean. The GDI objects that caused the leak are only found in that particular list and they aren't copied anywhere else. So theoretically, the "reference count" so to say should always be 1. They are however copied around inside the list a lot via RecreateFontHandles, AddFont itself (via the mentioned RtlMoveMemory) and RemoveFace (all 3 functions are found in misc.cpp).

Also can you please share with me the steps to repro the issue? i want to repro locally?

See the original issue #16297. I'm not entirely sure in which build the original leak fix is available, but the most recent internal dev builds should definitely have it. If you're on such a 25xxx build you can just launch the inbox conhost, then open the properties page, go to the "Font" tab and go through your font list. You should notice that almost all fonts look identical and pixelated. Otherwise, if you're on an older build, I'd be happy to send you a recent build of conhost.exe and console.dll. 🙂

@hussien89aa
Copy link

I cannot repro issue. in my local dev branch which has changes

image

image

@DHowett
Copy link
Member

DHowett commented Nov 21, 2023

I cannot repro issue.
image
@hussien89aa

That is the issue. That font is not Consolas. That is an impostor. 😄
Edit: Whoops, Leonard beat me to it!

@lhecker
Copy link
Member Author

lhecker commented Nov 21, 2023

Actually you can! Look closely at the first screenshot. That's not Consolas, but rather a bitmap font. 🙂
Edit: Ah whoops. We both responded simultaneously. 😅

@hussien89aa
Copy link

Okey my short answer here is that we know we have two problems, you cannot fix one regression and introduce another regression you know of. This is not a fix. You need to find a way to release GDI objects and avoid app crashes for reaching GDI objects limit that the first PR was for instead of just removing code.

@DHowett
Copy link
Member

DHowett commented Nov 27, 2023

Okay, here's the skinny.

  1. These aren't leaks, they are actively "in use" when the dialog is open.
  2. They will be freed when the dialog closes.
  3. We create one GDI font object for every monospaced font, in every size, in normal and bold weight.
  4. We need time to refactor the propsheet's font loader to cache the fonts on demand, rather than up front.
  5. This will stop the bleeding (active visual bug) and cause some other bleeding (sometimes, people with low GDI object thresholds will generate Leak Reports).

We're committing it for now and following up with an investigation into 3-4.

@DHowett DHowett merged commit 35240f2 into main Nov 27, 2023
14 of 16 checks passed
@DHowett DHowett deleted the dev/lhecker/16297-fontdlg-preview branch November 27, 2023 20:44
@DHowett DHowett moved this from To Cherry Pick to Rejected in 1.19 Servicing Pipeline Dec 4, 2023
@DHowett DHowett moved this from Rejected to To Cherry Pick in 1.19 Servicing Pipeline Jan 29, 2024
@DHowett
Copy link
Member

DHowett commented Jan 29, 2024

Ah, this failed cherry-pick into 1.19 because 1.19 hadn't merged inbox. I've brought inbox back into 1.19 and am bringing this PR in, to bring it back into inbox. 😵‍💫

@DHowett DHowett moved this from To Cherry Pick to Cherry Picked in 1.19 Servicing Pipeline Jan 29, 2024
DHowett pushed a commit that referenced this pull request Jan 29, 2024
After exiting the main loop in this function the invariant
`nFont <= NumberOfFonts` still holds true. Additionally,
preceding this removed code is this (paraphrased):
```cpp
if (nFont < NumberOfFonts) {
    RtlMoveMemory(...);
}
```
It ensures that the given slot `nFont` is always unoccupied by moving
it and all following items upwards if needed. As such, the call to
`DeleteObject` is always incorrect, as the slot is always "empty",
but may contain a copy of the previous occupant due to the `memmove`.

This regressed in 154ac2b.

Closes #16297

## Validation Steps Performed
* All fonts have a unique look in the preview panel ✅

(cherry picked from commit 35240f2)
Service-Card-Id: 91120871
Service-Version: 1.19
@DHowett DHowett moved this from Cherry Picked to Validated in 1.19 Servicing Pipeline Feb 21, 2024
@DHowett DHowett moved this from Validated to Shipped in 1.19 Servicing Pipeline Feb 21, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Area-Fonts Related to the font AutoMerge Marked for automatic merge by the bot when requirements are met Issue-Bug It either shouldn't be doing this or needs an investigation. Product-Conhost For issues in the Console codebase Severity-Blocking We won't ship a release like this! No-siree.
Projects
Development

Successfully merging this pull request may close these issues.

Font preview in host properties is broken after 154ac2b
4 participants