Skip to content

layout/fonts: Mitigate races related to quirks mode and fallback fonts#42960

Merged
mrobinson merged 1 commit intoservo:mainfrom
mrobinson:font-cache-race-condition
Mar 3, 2026
Merged

layout/fonts: Mitigate races related to quirks mode and fallback fonts#42960
mrobinson merged 1 commit intoservo:mainfrom
mrobinson:font-cache-race-condition

Conversation

@mrobinson
Copy link
Copy Markdown
Member

This change includes two related fixes for flakiness revealed by #42847.

  1. When caching fonts, try harder to not re-cache a font. This could
    happen due to a race condition with the read-write lock on the font
    cache. This change improves memory usage in some cases as it prevents
    a font from being loaded twice.
  2. Incorporate both the strut size and the block size contribution of a
    previously unused font in an inline container. Before the code was
    incorporating one or the other. In addition, only incorporate the
    block contribution of a previously unused font if its metrics
    meaningfully differ from the container's default font. This was the
    case triggered by failing to have the fix in part one of the change.

Testing: This fixes flakiness in an internal WPT-style test.
Fixes: #42908.

This change includes two related fixes for flakiness revealed by servo#42847.

1. When caching fonts, try harder to not re-cache a font. This could
   happen due to a race condition with the read-write lock on the font
   cache. This change improves memory usage in some cases as it prevents
   a font from being loaded twice.
2. Incorporate both the strut size and the block size contribution of a
   previously unused font in an inline container. Before the code was
   incorporating one or the other. In addition, *only* incorporate the
   block contribution of a previously unused font if its metrics
   meaningfully differ from the container's default font. This was the
   case triggered by failing to have the fix in part one of the change.

Co-authored-by: Oriol Brufau <[email protected]>
Co-authored-by: Luke Warlow <[email protected]>
Signed-off-by: Martin Robinson <[email protected]>
@servo-highfive servo-highfive added the S-awaiting-review There is new code that needs to be reviewed. label Mar 2, 2026
@Loirooriol Loirooriol added the T-linux-wpt Do a try run of the WPT label Mar 2, 2026
@github-actions github-actions bot removed the T-linux-wpt Do a try run of the WPT label Mar 2, 2026
@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 2, 2026

🔨 Triggering try run (#22586420167) for Linux (WPT)

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 2, 2026

Test results for linux-wpt from try job (#22586420167):

Flaky unexpected result (31)
  • TIMEOUT /FileAPI/url/url-in-tags-revoke.window.html (#19978)
    • TIMEOUT [expected PASS] subtest: Fetching a blob URL immediately before revoking it works in &lt;script&gt; tags.

      Test timed out
      

  • OK [expected TIMEOUT] /IndexedDB/idbfactory_open.any.worker.html
    • PASS [expected FAIL] subtest: Calling open() with version argument 1.5 should not throw.
    • PASS [expected TIMEOUT] subtest: Calling open() with version argument 9007199254740991 should not throw.
    • PASS [expected TIMEOUT] subtest: Calling open() with version argument undefined should not throw.
  • OK /_mozilla/mozilla/getBoundingClientRect.html (#39668)
    • FAIL [expected PASS] subtest: getBoundingClientRect 1

      assert_equals: expected 62 but got 60.35
      

  • CRASH [expected OK] /_webgl/conformance/uniforms/no-over-optimization-on-uniform-array-05.html
  • TIMEOUT [expected OK] /credential-management/credentialscontainer-frame-basics.https.html (#39430)
    • TIMEOUT [expected FAIL] subtest: navigator.credentials should be undefined in documents generated from data: URLs.

      Test timed out
      

  • OK /css/css-cascade/layer-cssom-order-reverse.html (#36094)
    • PASS [expected FAIL] subtest: Delete layer invalidates @font-face
  • OK [expected ERROR] /fetch/fetch-later/quota/same-origin-iframe/multiple-iframes.https.window.html (#35176)
  • OK /fetch/metadata/generated/css-font-face.sub.tentative.html (#34624)
    • PASS [expected FAIL] subtest: sec-fetch-storage-access - Not sent to non-trustworthy same-origin destination
  • OK [expected ERROR] /fetch/metadata/window-open.https.sub.html (#40339)
    • FAIL [expected PASS] subtest: Cross-site window, forced, reloaded

      The operation is insecure.
      

  • OK [expected ERROR] /focus/focus-event-after-switching-iframes.sub.html (#40368)
  • CRASH [expected OK] /html/browsers/browsing-the-web/navigating-across-documents/005.html (#27062)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-cross-origin.sub.window.html (#29056)
    • PASS [expected FAIL] subtest: Cross-origin navigation started from unload handler must be ignored
  • OK /html/browsers/browsing-the-web/navigating-across-documents/replace-before-load/a-click.html (#28697)
    • PASS [expected FAIL] subtest: aElement.click() before the load event must NOT replace
  • OK /html/browsers/history/the-history-interface/traverse_the_history_3.html (#21383)
    • PASS [expected FAIL] subtest: Multiple history traversals, last would be aborted
  • TIMEOUT [expected OK] /html/interaction/focus/the-autofocus-attribute/document-with-fragment-empty.html (#28259)
    • TIMEOUT [expected FAIL] subtest: Autofocus elements in top-level browsing context's documents with empty fragments should work.

      Test timed out
      

  • OK /html/semantics/document-metadata/the-meta-element/pragma-directives/attr-meta-http-equiv-refresh/allow-scripts-flag-changing-1.html (#39694)
    • PASS [expected FAIL] subtest: Meta refresh is blocked by the allow-scripts sandbox flag at its creation time, not when refresh comes due
  • OK /html/semantics/embedded-content/the-iframe-element/iframe-loading-lazy-nav-location-replace-set-src.html (#32697)
    • PASS [expected FAIL] subtest: Navigating iframe loading='lazy' and then setting src: location.replace
  • TIMEOUT [expected OK] /html/semantics/embedded-content/the-iframe-element/iframe_sandbox_navigate_other_frame_popup.sub.html (#39702)
    • TIMEOUT [expected FAIL] subtest: Sandboxed iframe can not navigate other frame's popup

      Test timed out
      

  • OK /html/semantics/scripting-1/the-script-element/module/dynamic-import/blob-url.any.worker.html (#33909)
    • FAIL [expected PASS] subtest: Revoking a blob URL immediately after calling import will not fail

      promise_test: Unhandled rejection with value: object "TypeError: Module fetching failed"
      

  • TIMEOUT [expected OK] /html/user-activation/navigation-state-reset-sameorigin.html
    • TIMEOUT [expected PASS] subtest: Post-navigation state reset.

      Test timed out
      

  • CRASH [expected OK] /html/webappapis/scripting/reporterror.any.worker.html
  • OK /navigation-timing/test-navigation-type-reload.html (#33334)
    • PASS [expected FAIL] subtest: Reload domComplete &gt; Original domComplete
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventEnd &gt; Original domContentLoadedEventEnd
    • PASS [expected FAIL] subtest: Reload domContentLoadedEventStart &gt; Original domContentLoadedEventStart
    • PASS [expected FAIL] subtest: Reload fetchStart &gt; Original fetchStart
    • PASS [expected FAIL] subtest: Reload loadEventEnd &gt; Original loadEventEnd
    • PASS [expected FAIL] subtest: Reload loadEventStart &gt; Original loadEventStart
  • PASS [expected FAIL] /png/apng/acTL-plays-two.html (#41191)
  • OK /resource-timing/buffer-full-add-then-clear.html (#40819)
    • FAIL [expected PASS] subtest: Test that if the buffer is cleared after entries were added to the secondary buffer, those entries make it into the primary one

      assert_equals: Number of entries does not match the expected value. expected 3 but got 0
      

  • OK /resource-timing/test_resource_timing.html (#25720)
    • PASS [expected FAIL] subtest: PerformanceEntry has correct name, initiatorType, startTime, and duration (xmlhttprequest)
  • TIMEOUT /trusted-types/trusted-types-navigation.html?06-10 (#37920)
    • TIMEOUT [expected FAIL] subtest: Navigate a frame via anchor with javascript:-urls in report-only mode.

      Test timed out
      

    • NOTRUN [expected TIMEOUT] subtest: Navigate a frame via anchor with javascript:-urls w/ default policy in report-only mode.
  • TIMEOUT [expected OK] /visual-viewport/resize-event-order.html (#41981)
    • TIMEOUT [expected FAIL] subtest: Popup: DOMWindow resize fired before VisualViewport.

      Test timed out
      

    • NOTRUN [expected PASS] subtest: iframe: DOMWindow resize fired before VisualViewport.
  • CRASH [expected OK] /webaudio/the-audio-api/the-mediastreamaudiodestinationnode-interface/closed-audiocontext-construction.html
  • OK /webdriver/tests/classic/element_click/user_prompts.py
    • FAIL [expected PASS] subtest: test_accept[alert-None]

      webdriver.error.NoSuchWindowException: no such window (404): No such window
      

  • OK /webdriver/tests/classic/element_send_keys/send_keys.py
    • FAIL [expected PASS] subtest: test_null_parameter_value

      webdriver.error.NoSuchWindowException: no such window (404): No such window
      

  • OK /webdriver/tests/classic/new_window/new.py
    • ERROR [expected PASS] subtest: test_no_top_browsing_context

      setup error: webdriver.error.NoSuchElementException: no such element (404)
      

Stable unexpected results that are known to be intermittent (16)
  • FAIL [expected PASS] /_mozilla/mozilla/sslfail.html (#10760)
  • TIMEOUT [expected OK] /_mozilla/mozilla/window_resize_event.html (#36741)
    • TIMEOUT [expected PASS] subtest: Popup onresize event fires after resizeTo

      Test timed out
      

  • OK /_webgl/conformance/textures/misc/texture-upload-size.html (#21770)
    • PASS [expected FAIL] subtest: WebGL test #45
    • PASS [expected FAIL] subtest: WebGL test #47
    • PASS [expected FAIL] subtest: WebGL test #49
    • PASS [expected FAIL] subtest: WebGL test #51
    • FAIL [expected PASS] subtest: WebGL test #53

      assert_true: Texture was smaller than the expected size 2x2 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #55

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : when calling texSubImage2D with the same texture upload with offset 1, 1 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #57

      assert_true: Texture was smaller than the expected size 2x2 expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #59

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : when calling texSubImage2D with the same texture upload with offset 1, 1 expected true got false
      

    • PASS [expected FAIL] subtest: WebGL test #61
    • PASS [expected FAIL] subtest: WebGL test #63
    • And 18 more unexpected results...
  • ERROR [expected CRASH] /_webgl/conformance2/textures/misc/tex-3d-size-limit.html (#42881)
    • PASS [expected FAIL] subtest: WebGL test #1
    • FAIL [expected PASS] subtest: WebGL test #3

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : texImage3D should fail for dimension out of range. expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #4

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : texImage3D should fail for dimension out of range. expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #5

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : texImage3D should fail for dimension out of range. expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #6

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : texImage3D should fail for dimension out of range. expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #7

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : texImage3D should fail for dimension out of range. expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #8

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : texImage3D should fail for dimension out of range. expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #9

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : texImage3D should fail for dimension out of range. expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #10

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : texImage3D should fail for dimension out of range. expected true got false
      

    • FAIL [expected PASS] subtest: WebGL test #11

      assert_true: getError expected: INVALID_VALUE. Was NO_ERROR : texImage3D should fail for dimension out of range. expected true got false
      

    • And 27 more unexpected results...
  • OK /beacon/beacon-basic.https.window.html (#41723)
    • PASS [expected FAIL] subtest: Payload size restriction should be accumulated: type = string
  • OK /css/css-fonts/generic-family-keywords-001.html (#37467)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(fangsong)
    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted generic(kai)

      assert_equals: quoted generic(kai) matches  @font-face rule expected 30 but got 50
      

    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted generic(khmer-mul)

      assert_equals: quoted generic(khmer-mul) matches  @font-face rule expected 30 but got 50
      

    • FAIL [expected PASS] subtest: @font-face matching for quoted and unquoted generic(nastaliq)

      assert_equals: quoted generic(nastaliq) matches  @font-face rule expected 30 but got 50
      

  • OK /css/css-fonts/generic-family-keywords-003.html (#38994)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted sans-serif (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted cursive (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted fantasy (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted monospace (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted system-ui (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted math (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(fangsong) (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted generic(khmer-mul) (drawing text in a canvas)
    • PASS [expected FAIL] subtest: @font-face matching for quoted and unquoted ui-serif (drawing text in a canvas)
  • TIMEOUT [expected OK] /fetch/api/redirect/redirect-keepalive.https.any.html (#32153)
    • TIMEOUT [expected PASS] subtest: [keepalive][iframe][load] mixed content redirect; setting up

      Test timed out
      

  • ERROR [expected OK] /fetch/fetch-later/quota/same-origin-iframe/accumulated-oversized-payload.https.window.html (#41705)
  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin-fragment.html (#20768)
    • FAIL [expected PASS] subtest: Tests that a fragment navigation in the unload handler will not block the initial navigation

      assert_equals: expected "" but got "#fragment"
      

  • OK /html/browsers/browsing-the-web/navigating-across-documents/navigation-unload-same-origin.window.html (#29049)
    • FAIL [expected PASS] subtest: Same-origin navigation started from unload handler must be ignored

      assert_equals: expected "?pass" but got "?fail"
      

  • OK [expected TIMEOUT] /html/interaction/focus/the-autofocus-attribute/supported-elements.html (#24145)
    • FAIL [expected NOTRUN] subtest: Host element with delegatesFocus should support autofocus

      assert_equals: expected Element node &lt;div autofocus=""&gt;&lt;/div&gt; but got Element node &lt;body&gt;&lt;div autofocus=""&gt;&lt;/div&gt;&lt;/body&gt;
      

    • FAIL [expected NOTRUN] subtest: Host element with delegatesFocus including no focusable descendants should be skipped

      assert_equals: expected Element node &lt;input autofocus=""&gt;&lt;/input&gt; but got Element node &lt;body&gt;&lt;/body&gt;
      

    • FAIL [expected NOTRUN] subtest: Area element should support autofocus

      assert_equals: expected Element node &lt;area autofocus="" href="/common/blank.html"&gt;&lt;/area&gt; but got Element node &lt;body&gt;
      &lt;img src="/media/poster.png" usemap="#map"&gt;
      &lt;map n...
      

  • OK /html/semantics/scripting-1/the-script-element/execution-timing/077.html (#22139)
    • FAIL [expected PASS] subtest: adding several types of scripts through the DOM and removing some of them confuses scheduler

      assert_array_equals: expected property 1 to be "Script #1 ran" but got "Script #3 ran" (expected array ["Script #2 ran", "Script #1 ran", "Script #3 ran", "Script #4 ran"] got ["Script #2 ran", "Script #3 ran", "Script #4 ran", "Script #1 ran"])
      

  • OK /html/webappapis/user-prompts/print-during-unload.html (#35944)
    • PASS [expected FAIL] subtest: print() during unload
  • TIMEOUT /trusted-types/trusted-types-navigation.html?31-35 (#38034)
    • TIMEOUT [expected PASS] subtest: Navigate a frame via form-submission with javascript:-urls in report-only mode.

      Test timed out
      

  • OK [expected TIMEOUT] /webstorage/localstorage-about-blank-3P-iframe-opens-3P-window.partitioned.html (#29053)
    • PASS [expected TIMEOUT] subtest: StorageKey: test 3P about:blank window opened from a 3P iframe

@github-actions
Copy link
Copy Markdown

github-actions bot commented Mar 2, 2026

✨ Try run (#22586420167) succeeded.

@servo-highfive servo-highfive removed the S-awaiting-review There is new code that needs to be reviewed. label Mar 3, 2026
@mrobinson mrobinson added this pull request to the merge queue Mar 3, 2026
@servo-highfive servo-highfive added the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Mar 3, 2026
Merged via the queue into servo:main with commit 027910e Mar 3, 2026
71 checks passed
@mrobinson mrobinson deleted the font-cache-race-condition branch March 3, 2026 21:59
@servo-highfive servo-highfive removed the S-awaiting-merge The PR is in the process of compiling and running tests on the automated CI. label Mar 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Intermittent FAIL in /_mozilla/css/img_size_a.html

3 participants