Startup crash in [@ gfxDWriteFontList::InitSharedFontListForPlatform]
Categories
(Core :: Graphics: Text, defect)
Tracking
()
| Tracking | Status | |
|---|---|---|
| firefox-esr115 | --- | unaffected |
| firefox-esr140 | --- | unaffected |
| firefox142 | --- | wontfix |
| firefox143 | --- | wontfix |
| firefox144 | --- | wontfix |
| firefox145 | --- | wontfix |
| firefox146 | --- | fix-optional |
People
(Reporter: release-mgmt-account-bot, Assigned: jfkthame, NeedInfo)
References
(Blocks 1 open bug)
Details
(4 keywords)
Crash Data
Attachments
(2 files)
Crash report: https://crash-stats.mozilla.org/report/index/61f4de50-46d6-4ce2-b072-1cd3e0250821
Reason: EXCEPTION_ACCESS_VIOLATION_READ
Top 10 frames of crashing thread:
0 xul.dll gfxDWriteFontList::InitSharedFontListForPlatform gfx/thebes/gfxDWriteFontList.cpp:1585
1 xul.dll gfxPlatformFontList::InitFontList gfx/thebes/gfxPlatformFontList.cpp:681
2 xul.dll gfxPlatformFontList::Initialize gfx/thebes/gfxPlatformFontList.cpp:286
3 xul.dll gfxWindowsPlatform::CreatePlatformFontList gfx/thebes/gfxWindowsPlatform.cpp:614
4 xul.dll gfxPlatform::Init gfx/thebes/gfxPlatform.cpp:989
5 xul.dll gfxPlatform::InitChild gfx/thebes/gfxPlatform.cpp:456
5 xul.dll mozilla::dom::ContentChild::InitGraphicsDeviceData dom/ipc/ContentChild.cpp:1331
5 xul.dll mozilla::dom::ContentChild::RecvSetXPCOMProcessAttributes dom/ipc/ContentChild.cpp:681
6 xul.dll mozilla::dom::PContentChild::OnMessageReceived ipc/ipdl/PContentChild.cpp:11714
7 xul.dll mozilla::ipc::MessageChannel::DispatchAsyncMessage ipc/glue/MessageChannel.cpp:1797
By querying Nightly crashes reported within the last 2 months, here are some insights about the signature:
- First crash report: 2025-07-21
- Process type: Multiple distinct types
- Is startup crash: Yes - 15 out of 19 crashes happened during startup
- Has user comments: No
- Is null crash: Yes - all crashes happened on null or near null memory address
Comment 1•1 year ago
|
||
These are null deref crashes. It looks like maybe factory is null here?
RefPtr<IDWriteFactory> factory = Factory::GetDWriteFactory();
HRESULT hr = factory->GetGdiInterop(getter_AddRefs(mGDIInterop));
This crash has happened recently on 141 and 142, but there's been a big spike on Nightly starting with the 20250819090810 build. There's nothing obviously font or graphics related that was added in that build.
This could be some kind of startup change, but some of the crashes are in the child process and consistently happening in RecvSetXPCOMProcessAttributes so that should be fairly consistent.
Jonathan, any ideas? Thanks.
Updated•1 year ago
|
Updated•1 year ago
|
| Assignee | ||
Comment 2•1 year ago
|
||
Yeah, it's not obvious to me what may have caused this to spike. I'd guess perhaps something has affected timings during startup.
Possibly we should be calling EnsureDWriteFactory rather than GetDWriteFactory here, if we don't have a guarantee that we'll have initialized the factory before we attempt to initialize the font list.
(I think we've seen some issues before where it appeared that we failed to get the Factory; see the code at https://searchfox.org/firefox-main/rev/995b0c65366602cbb70a65131f9a848c82a8d19d/gfx/2d/Factory.cpp#895-904 that Jeff added back in bug 1675906, when we were trying to understand where these could be coming from.)
| Assignee | ||
Comment 3•1 year ago
|
||
From skimming through gfxPlatform::Init(), it looks like the DWrite Factory should have been initialized via InitAcceleration() prior to attempting to initialize the platform font-list. But if that failed for some reason, I guess we might end up crashing here.
Not sure if using EnsureDWriteFactory will help anything, as it might just fail again and we'll still crash, but at least it might give us some error logging closer to the point of failure?
| Assignee | ||
Comment 4•1 year ago
|
||
The other thing we might be able to do is to get rid of the gfxDWriteFontList::mGDIInterop that we're initializing here altogether, which would eliminate this use of the factory. I'm not sure if we still need it, given that with win32-lockdown, we won't be using the GDI-table-loading code path any more. (But I suspect that if the root cause here is a failure to initialize the dwrite factory, that'll just push the crash to a new location.)
| Assignee | ||
Comment 5•1 year ago
|
||
Updated•1 year ago
|
| Assignee | ||
Comment 6•1 year ago
|
||
I suggest we do this to make the code somewhat more robust, in principle; at least, it should "do no harm". Though I suspect it may not actually help if the real issue is a some kind of underlying dwrite initialization failure.
| Assignee | ||
Updated•1 year ago
|
| Assignee | ||
Comment 7•1 year ago
|
||
Marking this as leave-open for now, as I'm doubtful the patch above will actually prevent such crashes.
Comment 9•1 year ago
|
||
| bugherder | ||
Updated•1 year ago
|
Updated•1 year ago
|
Comment 10•1 year ago
|
||
:jfkthame any followup patches for this crash? It looks like there was only one in b2 post landing of the fix
Updated•1 year ago
|
Updated•11 months ago
|
| Assignee | ||
Comment 11•11 months ago
|
||
(In reply to Dianna Smith [:diannaS] from comment #10)
:jfkthame any followup patches for this crash? It looks like there was only one in b2 post landing of the fix
No new ideas at the moment. (FWIW, I see there are a handful of reports from 146 as well.)
It seems clear that what's happening is the Factory::EnsureDWriteFactory(); call fails, and so we crash with a null-deref as soon as we try to call a method on the (null) factory pointer.
But I don't have any insight into why the EnsureDWriteFactory call is (very occasionally) failing, or what we can do about it.
(ni? to Lee in case he has any further ideas here.)
| Assignee | ||
Comment 12•11 months ago
|
||
One thing I notice is that EnsureDWriteFactory() unconditionally sets the mDWriteFactoryInitialized flag, regardless of whether it succeeds in initializing a factory. This means that if it fails, and we subsequently call EnsureDWriteFactory() again, it won't actually attempt the initialization again but will immediately return the null pointer.
I suggest that instead, it should always try to initialize the factory if currently null. That way, if the first call fails, but we call Ensure... again (e.g. from this call-site in the font-list code), we get a second bite at the cherry. If the initial failure was a transient issue, perhaps it'll work now. At least, it can't hurt to try, afaics.
| Assignee | ||
Comment 13•11 months ago
|
||
Comment 14•11 months ago
|
||
Presumably if its failing and then succeeding, we just haven't set up D3D11/DWrite yet this early in startup.
It might warrant further investigation why we're trying to access DWrite before that initialization has occurred.
Comment 15•11 months ago
|
||
Comment 16•11 months ago
|
||
| bugherder | ||
Updated•11 months ago
|
| Reporter | ||
Comment 17•5 months ago
|
||
The leave-open keyword is there and there is no activity for 6 months.
:jfkthame, maybe it's time to close this bug?
For more information, please visit BugBot documentation.
Description
•