commit a70a0ebf9aa5b868ae15c06fdbbbc92244c743b6
parent 51d5dea24d047b55facba470e6aeafc752a44698
Author: Bob Owen <bobowencode@gmail.com>
Date: Thu, 20 Nov 2025 11:24:28 +0000
Bug 1967071 p2 - Annotate and crash when no font file found for WR NativeFontHandle. r=jwatt
This is only on Windows Nightly to try and diagnose the issue.
Differential Revision: https://phabricator.services.mozilla.com/D273059
Diffstat:
6 files changed, 66 insertions(+), 1 deletion(-)
diff --git a/Cargo.lock b/Cargo.lock
@@ -7911,6 +7911,7 @@ dependencies = [
"gecko-profiler",
"gleam",
"log",
+ "mozbuild",
"nsstring",
"num_cpus",
"objc",
diff --git a/gfx/layers/wr/WebRenderBridgeParent.cpp b/gfx/layers/wr/WebRenderBridgeParent.cpp
@@ -123,6 +123,8 @@ static CrashReporter::Annotation FromWrCrashAnnotation(
return CrashReporter::Annotation::GraphicsCompileShader;
case mozilla::wr::CrashAnnotation::DrawShader:
return CrashReporter::Annotation::GraphicsDrawShader;
+ case mozilla::wr::CrashAnnotation::FontFile:
+ return CrashReporter::Annotation::GraphicsFontFile;
default:
MOZ_ASSERT_UNREACHABLE("Unhandled annotation!");
return CrashReporter::Annotation::Count;
diff --git a/gfx/webrender_bindings/Cargo.toml b/gfx/webrender_bindings/Cargo.toml
@@ -23,6 +23,7 @@ wr_malloc_size_of = { path = "../wr/wr_malloc_size_of" }
gecko-profiler = { path = "../../tools/profiler/rust-api" }
static_prefs = { path = "../../modules/libpref/init/static_prefs" }
remove_dir_all = "0.5.3"
+mozbuild = "0.1"
[dependencies.webrender]
path = "../wr/webrender"
diff --git a/gfx/webrender_bindings/src/moz2d_renderer.rs b/gfx/webrender_bindings/src/moz2d_renderer.rs
@@ -35,6 +35,19 @@ use core_graphics::font::CGFont;
#[cfg(any(target_os = "macos", target_os = "ios"))]
use foreign_types::ForeignType;
+#[cfg(target_os = "windows")]
+use std::ffi::CStr;
+#[cfg(target_os = "windows")]
+use std::ffi::OsStr;
+#[cfg(target_os = "windows")]
+use std::iter::FromIterator;
+#[cfg(target_os = "windows")]
+use std::os::raw::c_char;
+#[cfg(target_os = "windows")]
+use std::path::PathBuf;
+#[cfg(target_os = "windows")]
+use winapi::um::errhandlingapi::GetLastError;
+
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
use std::ffi::CString;
#[cfg(not(any(target_os = "macos", target_os = "ios", target_os = "windows")))]
@@ -742,7 +755,8 @@ extern "C" {
);
fn DeleteBlobFont(key: WrFontInstanceKey);
fn ClearBlobImageResources(namespace: WrIdNamespace);
-
+ #[cfg(target_os = "windows")]
+ fn gfx_wr_set_crash_annotation(annotation: CrashAnnotation, value: *const c_char);
}
impl Moz2dBlobImageHandler {
@@ -761,6 +775,42 @@ impl Moz2dBlobImageHandler {
/// Currently just sets up fonts found in the blob.
fn prepare_request(&self, blob: &[u8], resources: &dyn BlobImageResources) {
#[cfg(target_os = "windows")]
+ fn maybe_crash_on_no_font_file(font_path: &PathBuf) {
+ if !mozbuild::config::NIGHTLY_BUILD {
+ return;
+ }
+
+ // On Nightly add annotation of the error and font file path then crash. We strip
+ // the user's dir if necessary to try to prevent capturing personal information.
+ let end_of_path = PathBuf::from_iter(
+ font_path
+ .components()
+ .skip_while(|c| !c.as_os_str().eq_ignore_ascii_case(OsStr::new("users")))
+ .skip(2),
+ );
+ // end_of_path will be empty if we don't find the Users dir.
+ let annotation_path = if end_of_path.as_os_str().is_empty() {
+ font_path.as_os_str()
+ } else {
+ end_of_path.as_os_str()
+ };
+ let annotation_string = format!(
+ "Error: {:x} loading: {}",
+ unsafe { GetLastError() },
+ annotation_path.display()
+ );
+ unsafe {
+ gfx_wr_set_crash_annotation(
+ CrashAnnotation::FontFile,
+ CStr::from_bytes_with_nul(annotation_string.as_bytes())
+ .unwrap()
+ .as_ptr(),
+ );
+ }
+ panic!("Moz2D font file not found");
+ }
+
+ #[cfg(target_os = "windows")]
fn process_native_font_handle(key: FontKey, handle: &NativeFontHandle) {
if let Some(file) = dwrote::FontFile::new_from_path(&handle.path) {
if let Ok(face) = file.create_face(handle.index, dwrote::DWRITE_FONT_SIMULATIONS_NONE) {
@@ -768,6 +818,9 @@ impl Moz2dBlobImageHandler {
return;
}
}
+
+ maybe_crash_on_no_font_file(&handle.path);
+
// Failed to open the font file? Try to set up a fallback font so that
// we don't simply crash, although text will be garbage.
let desc = dwrote::FontDescriptor {
diff --git a/gfx/wr/webrender_api/src/lib.rs b/gfx/wr/webrender_api/src/lib.rs
@@ -805,6 +805,7 @@ pub enum ScrollLocation {
pub enum CrashAnnotation {
CompileShader = 0,
DrawShader = 1,
+ FontFile = 2,
}
/// Handler to expose support for annotating crash reports.
diff --git a/toolkit/crashreporter/CrashAnnotations.yaml b/toolkit/crashreporter/CrashAnnotations.yaml
@@ -554,6 +554,13 @@ GraphicsDrawShader:
type: string
scope: report
+GraphicsFontFile:
+ description: >
+ Error and path of the font file that has failed to load. The user's profile
+ dir is removed from the front of the path if necessary.
+ type: string
+ scope: report
+
GraphicsNumActiveRenderers:
description: >
Number of webrender renderer instances that are not in a paused state.