Bug 155009 - [Font Loading] Crash when a single load request causes multiple fonts to fail loading
Summary: [Font Loading] Crash when a single load request causes multiple fonts to fail...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: New Bugs (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Myles C. Maxfield
URL:
Keywords: InRadar
Depends on:
Blocks:
 
Reported: 2016-03-03 20:57 PST by Myles C. Maxfield
Modified: 2016-03-08 14:22 PST (History)
5 users (show)

See Also:


Attachments
Patch (5.64 KB, patch)
2016-03-03 20:59 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Archive of layout-test-results from ews116 for mac-yosemite (818.54 KB, application/zip)
2016-03-03 21:58 PST, Build Bot
no flags Details
WIP (6.01 KB, patch)
2016-03-04 00:33 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (13.85 KB, patch)
2016-03-04 10:12 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (13.86 KB, patch)
2016-03-04 10:27 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff
Patch (13.85 KB, patch)
2016-03-04 12:12 PST, Myles C. Maxfield
simon.fraser: review+
Details | Formatted Diff | Diff
Patch for committing (15.72 KB, patch)
2016-03-04 14:10 PST, Myles C. Maxfield
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Myles C. Maxfield 2016-03-03 20:57:30 PST
[Font Loading] Crash when multiple fonts fail
Comment 1 Myles C. Maxfield 2016-03-03 20:59:42 PST
Created attachment 272826 [details]
Patch
Comment 2 Myles C. Maxfield 2016-03-03 21:01:48 PST
<rdar://problem/24865887>
Comment 3 Darin Adler 2016-03-03 21:16:25 PST
Comment on attachment 272826 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=272826&action=review

> Source/WebCore/css/CSSFontFace.cpp:385
> +        if (m_clients.contains(client))

What is this m_clients.contains check supposed to do? It can’t correctly handle the case where a client is deleted and removed from the set of clients, because it’s possible that the client was removed, deleted, a new object allocated at the same address, and the new object added as a client, all before the call to contains happens, falsely returning true even though it’s a different object.

Making a copy and doing this contains check is a common pattern people try to use to fix this category of problem, but it’s an incorrect one. There are correct solutions to this kind of iteration, but they typically involve storing a pointer to the local temporary set being iterated in the object and having remove do removal from both sets, and other techniques like that.
Comment 4 Build Bot 2016-03-03 21:58:15 PST
Comment on attachment 272826 [details]
Patch

Attachment 272826 [details] did not pass mac-debug-ews (mac):
Output: http://webkit-queues.webkit.org/results/920410

New failing tests:
fast/text/font-face-set-document-multiple-failure.html
Comment 5 Build Bot 2016-03-03 21:58:17 PST
Created attachment 272832 [details]
Archive of layout-test-results from ews116 for mac-yosemite

The attached test failures were seen while running run-webkit-tests on the mac-debug-ews.
Bot: ews116  Port: mac-yosemite  Platform: Mac OS X 10.10.5
Comment 6 Myles C. Maxfield 2016-03-04 00:18:06 PST
The failure is WK1-specific.
Comment 7 Myles C. Maxfield 2016-03-04 00:33:56 PST
Created attachment 272841 [details]
WIP
Comment 8 Myles C. Maxfield 2016-03-04 10:12:19 PST
Created attachment 273010 [details]
Patch
Comment 9 Myles C. Maxfield 2016-03-04 10:27:32 PST
Created attachment 273015 [details]
Patch
Comment 10 Simon Fraser (smfr) 2016-03-04 12:06:40 PST
fail to what?
Comment 11 Myles C. Maxfield 2016-03-04 12:12:12 PST
Created attachment 273022 [details]
Patch
Comment 12 Simon Fraser (smfr) 2016-03-04 13:06:36 PST
Comment on attachment 273022 [details]
Patch

View in context: https://bugs.webkit.org/attachment.cgi?id=273022&action=review

> Source/WebCore/ChangeLog:18
> +        * css/CSSFontFace.cpp:
> +        (WebCore::CSSFontFace::setStatus):
> +        * css/FontFaceSet.cpp:
> +        (WebCore::FontFaceSet::faceFinished):
> +        * css/FontFaceSet.h:

This doesn't mention the Document::fonts() change.

> Source/WebCore/css/CSSFontFace.cpp:57
> +        clientsCopy.append(client);

I think this can be an uncheckedAppend()

> Source/WebCore/dom/Document.cpp:6686
> +    updateStyleIfNeeded();

This should be explained in the changelog.
Comment 13 Myles C. Maxfield 2016-03-04 14:10:16 PST
Created attachment 273038 [details]
Patch for committing
Comment 14 Darin Adler 2016-03-05 18:28:44 PST
Comment on attachment 273038 [details]
Patch for committing

View in context: https://bugs.webkit.org/attachment.cgi?id=273038&action=review

> Source/WebCore/ChangeLog:9
> +        In Javascript, the first promise fulfilment/failure wins. However, in C++, any
> +        subsequent fulfulments/failures cause a crash.

JavaScript has a capital S in it.

Typo: it should be "fulfillment", not "fulfilment" or "fulfulment".

> Source/WebCore/css/CSSFontFace.cpp:51
> +template <typename T>

No space after the word template before the "<" in our coding style. I also like putting this all one one line rather than one template line and a separate function signature line.

> Source/WebCore/css/CSSFontFace.cpp:58
> +        client->guardAgainstClientRegistrationChanges();

If we arranged things so that the client class had functions named ref/deref that call through to the virtual functions, then we could use a Vector<Ref<CSSFontFace::Client>> (or maybe RefPtr instead of Ref) and not have to write as much code. This is the pattern we use in EventTarget, for example. This template could be even more generic then.

> Source/WebCore/css/CSSFontFace.h:115
> +        virtual void guardAgainstClientRegistrationChanges() { };
> +        virtual void stopGuardingAgainstClientRegistrationChanges() { };

The semicolons are unneeded/incorrect. I see the same problem on previous lines of code.

> Source/WebCore/css/FontFaceSet.h:104
> +        bool terminalState { false };

Not too fond of this name. It’s called terminal state, but the variable doesn’t contain a terminal state or contain a state at all.

Our normal style is to name booleans with clauses that fit the form "promise <xxx>", so it could be a name like hasReachedTerminalState.
Comment 15 Darin Adler 2016-03-05 18:30:30 PST
Comment on attachment 273038 [details]
Patch for committing

View in context: https://bugs.webkit.org/attachment.cgi?id=273038&action=review

> Source/WebCore/css/FontFace.cpp:393
> +    ref();

A good comment here would be something like:

    // This class's destructor is what removes it as a client; a ref is what it takes to prevent that from happening.
Comment 16 Myles C. Maxfield 2016-03-08 14:22:30 PST
Committed r197804: <http://trac.webkit.org/changeset/197804>