Open Bug 1985422 Opened 1 year ago Updated 5 months ago

Startup crash in [@ gfxDWriteFontList::InitSharedFontListForPlatform]

Categories

(Core :: Graphics: Text, defect)

Unspecified
Windows
defect

Tracking

()

ASSIGNED
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

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.

Component: General → Graphics: Text
Flags: needinfo?(jfkthame)
Keywords: regression
Severity: -- → S3

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.)

Flags: needinfo?(jfkthame)

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?

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: nobody → jfkthame
Status: NEW → ASSIGNED

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.

Hardware: x86 → Unspecified

Marking this as leave-open for now, as I'm doubtful the patch above will actually prevent such crashes.

Keywords: leave-open
Pushed by jkew@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/88cc72be7f51 https://hg.mozilla.org/integration/autoland/rev/fc00bdbb8f2e Use EnsureDWriteFactory during InitSharedFontListForPlatform, in case it hasn't been initialized yet. r=gfx-reviewers,lsalzman

:jfkthame any followup patches for this crash? It looks like there was only one in b2 post landing of the fix

Flags: needinfo?(jfkthame)

(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.)

Flags: needinfo?(jfkthame) → needinfo?(lsalzman)

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.

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.

Flags: needinfo?(lsalzman)
Pushed by jkew@mozilla.com: https://github.com/mozilla-firefox/firefox/commit/f0182f011584 https://hg.mozilla.org/integration/autoland/rev/2d370b15068c Don't record DWriteFactory as being initialized unless it succeeded. r=lsalzman
Regressions: 1999396
No longer regressions: 1999396

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.

Flags: needinfo?(jfkthame)
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: