Bug 174760 - [GTK] Icon database error and crash
Summary: [GTK] Icon database error and crash
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKitGTK (show other bugs)
Version: Other
Hardware: PC Linux
: P2 Major
Assignee: Nobody
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-07-23 07:10 PDT by Michael Catanzaro
Modified: 2017-07-24 23:39 PDT (History)
7 users (show)

See Also:


Attachments
Patch (2.35 KB, patch)
2017-07-24 01:11 PDT, Carlos Garcia Campos
mcatanzaro: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Michael Catanzaro 2017-07-23 07:10:23 PDT
Seems the icon database is broken after the recent changes. Every time I start Epiphany I get this lovely warning:

ERROR: Failed to start load for icon at url /favicon.ico
../../Source/WebCore/loader/icon/IconLoader.cpp(96) : void WebCore::IconLoader::startLoading()

Now, right click on any page and click Save As. The UI process will crash. (This might be two different bugs.)

#0  0x00007f6ef51168f9 in WTFCrash ()
    at ../../Source/WTF/wtf/Assertions.cpp:278
No locals.
#1  0x00007f6efcfdb8fc in (anonymous namespace)::TimerBase::stop (
    this=0x7f6ee2a6f108) at ../../Source/WebCore/platform/Timer.cpp:214
        __PRETTY_FUNCTION__ = "void WebCore::TimerBase::stop()"
#2  0x00007f6efcfdb7b2 in (anonymous namespace)::TimerBase::~TimerBase (
    this=0x7f6ee2a6f108, __in_chrg=<optimized out>)
    at ../../Source/WebCore/platform/Timer.cpp:197
No locals.
#3  0x00007f6efb99042c in (anonymous namespace)::Timer::~Timer (
    this=0x7f6ee2a6f108, __in_chrg=<optimized out>)
    at ../../Source/WebCore/platform/Timer.h:116
No locals.
#4  0x00007f6efd0b489c in (anonymous namespace)::Image::~Image (
    this=0x7f6ee2a6f0e8, __in_chrg=<optimized out>)
    at ../../Source/WebCore/platform/graphics/Image.cpp:55
No locals.
#5  0x00007f6efd038382 in (anonymous namespace)::BitmapImage::~BitmapImage (
    this=0x7f6ee2a6f0e8, __in_chrg=<optimized out>)
    at ../../Source/WebCore/platform/graphics/BitmapImage.cpp:61
No locals.
#6  0x00007f6efd03839e in (anonymous namespace)::BitmapImage::~BitmapImage (
    this=0x7f6ee2a6f0e8, __in_chrg=<optimized out>)
    at ../../Source/WebCore/platform/graphics/BitmapImage.cpp:67
No locals.
#7  0x00007f6efba9b1de in WTF::RefCounted<WebCore::Image>::deref (
    this=0x7f6ee2a6f0f0) at ../../Source/WTF/wtf/RefCounted.h:145
No locals.
#8  0x00007f6efba98cbc in WTF::derefIfNotNull<WebCore::Image> (
    ptr=0x7f6ee2a6f0e8) at ../../Source/WTF/wtf/RefPtr.h:45
No locals.
#9  0x00007f6efba967a5 in WTF::RefPtr<WebCore::Image>::~RefPtr (
    this=0x7f6ee2af3888, __in_chrg=<optimized out>)
    at ../../Source/WTF/wtf/RefPtr.h:69
No locals.
#10 0x00007f6efbf334eb in (anonymous namespace)::IconDatabase::IconRecord::~IconRecord (this=0x7f6ee2af3870, __in_chrg=<optimized out>)
    at ../../Source/WebKit/UIProcess/API/glib/IconDatabase.cpp:105
No locals.
#11 0x00007f6efbf41fe9 in WTF::RefCounted<WebKit::IconDatabase::IconRecord>::deref (this=0x7f6ee2af3870) at ../../Source/WTF/wtf/RefCounted.h:145
No locals.
#12 0x00007f6efbf420db in WTF::derefIfNotNull<WebKit::IconDatabase::IconRecord>
    (ptr=0x7f6ee2af3870) at ../../Source/WTF/wtf/RefPtr.h:45
No locals.
#13 0x00007f6efbf404e5 in WTF::RefPtr<WebKit::IconDatabase::IconRecord>::~RefPtr (this=0x7f6ee2a74890, __in_chrg=<optimized out>)
    at ../../Source/WTF/wtf/RefPtr.h:69
No locals.
#14 0x00007f6efbf337f9 in (anonymous namespace)::IconDatabase::PageURLRecord::~PageURLRecord (this=0x7f6ee2a74888, __in_chrg=<optimized out>)
    at ../../Source/WebKit/UIProcess/API/glib/IconDatabase.cpp:164
No locals.
#15 0x00007f6efbf352ba in (anonymous namespace)::IconDatabase::performReleaseIconForPageURL (this=0x7f6ee2acc000, pageURLOriginal=..., releaseCount=1)
    at ../../Source/WebKit/UIProcess/API/glib/IconDatabase.cpp:536
        __PRETTY_FUNCTION__ = "void WebKit::IconDatabase::performReleaseIconForPageURL(const WTF::String&, int)"
        pageRecord = 0x7f6ee2a74888
        iconRecord = 0x7f6ee2af3870
#16 0x00007f6efbf39451 in (anonymous namespace)::IconDatabase::performPendingRetainAndReleaseOperations (this=0x7f6ee2acc000)
    at ../../Source/WebKit/UIProcess/API/glib/IconDatabase.cpp:1369
        entry = @0x7f6ee2aa4690: {key = {m_impl = {
              static isRefPtr = <optimized out>, m_ptr = 0x7f6ee2afc780}}, 
          value = 1}
        __for_range = @0x7f6e92a9e920: {m_impl = {m_impl = {
              static m_maxLoad = 2, static m_minLoad = 6, 
              m_table = 0x7f6ee2aa4680, m_tableSize = 8, m_tableSizeMask = 7, 
              m_keyCount = 1, m_deletedCount = 0, 
              m_iterators = 0x7f6e92a9e8e8, 
              m_mutex = std::unique_ptr<WTF::Lock> containing 0x7f6ee2aba088}}}
        __for_begin = {<std::iterator<std::forward_iterator_tag, WTF::KeyValuePair<WTF::String, unsigned int>, long, WTF::KeyValuePair<WTF::String, unsigned int>*, WTF::KeyValuePair<WTF::String, unsigned int>&>> = {<No data fields>}, 
          m_impl = {<std::iterator<std::forward_iterator_tag, WTF::KeyValuePair<WTF::String, unsigned int>, long, WTF::KeyValuePair<WTF::String, unsigned int>*, WTF::KeyValuePair<WTF::String, unsigned int>&>> = {<No data fields>}, 
            m_iterator = {<std::iterator<std::forward_iterator_tag, WTF::KeyValuePair<WTF::String, unsigned int>, long, WTF::KeyValuePair<WTF::String, unsigned int> const*, WTF::KeyValuePair<WTF::String, unsigned int> const&>> = {<No data fields>}, m_position = 0x7f6ee2aa4690, m_endPosition = 0x7f6ee2aa4700, 
              m_table = 0x7f6e92a9e920, m_next = 0x0, 
              m_previous = 0x7f6e92a9e8e8}}}
        __for_end = {<std::iterator<std::forward_iterator_tag, WTF::KeyValuePair<WTF::String, unsigned int>, long, WTF::KeyValuePair<WTF::String, unsigned int>*, WTF::KeyValuePair<WTF::String, unsigned int>&>> = {<No data fields>}, 
          m_impl = {<std::iterator<std::forward_iterator_tag, WTF::KeyValuePair<WTF::String, unsigned int>, long, WTF::KeyValuePair<WTF::String, unsigned int>*, WTF::KeyValuePair<WTF::String, unsigned int>&>> = {<No data fields>}, 
            m_iterator = {<std::iterator<std::forward_iterator_tag, WTF::KeyValuePair<WTF::String, unsigned int>, long, WTF::KeyValuePair<WTF::String, unsigned int> const*, WTF::KeyValuePair<WTF::String, unsigned int> const&>> = {<No data fields>}, m_position = 0x7f6ee2aa4700, m_endPosition = 0x7f6ee2aa4700, 
              m_table = 0x7f6e92a9e920, m_next = 0x7f6e92a9e8b8, 
              m_previous = 0x0}}}
        __PRETTY_FUNCTION__ = "void WebKit::IconDatabase::performPendingRetainAndReleaseOperations()"
        toRetain = {m_impl = {m_impl = {static m_maxLoad = 2, 
              static m_minLoad = 6, m_table = 0x0, m_tableSize = 0, 
              m_tableSizeMask = 0, m_keyCount = 0, m_deletedCount = 0, 
              m_iterators = 0x0, 
              m_mutex = std::unique_ptr<WTF::Lock> containing 0x7f6ee2aba080}}}
        toRelease = {m_impl = {m_impl = {static m_maxLoad = 2, 
              static m_minLoad = 6, m_table = 0x7f6ee2aa4680, m_tableSize = 8, 
              m_tableSizeMask = 7, m_keyCount = 1, m_deletedCount = 0, 
              m_iterators = 0x7f6e92a9e8e8, 
              m_mutex = std::unique_ptr<WTF::Lock> containing 0x7f6ee2aba088}}}
#17 0x00007f6efbf38f3a in (anonymous namespace)::IconDatabase::syncThreadMainLoop (this=0x7f6ee2acc000)
    at ../../Source/WebKit/UIProcess/API/glib/IconDatabase.cpp:1276
        locker = {<WTF::AbstractLocker> = {<No data fields>}, 
          m_lockable = 0x7f6ee2acc064}
        timeStamp = 3175.4553249999999
        didAnyWork = false
        newstamp = 3170.4540929999998
        __PRETTY_FUNCTION__ = "void WebKit::IconDatabase::syncThreadMainLoop()"
#18 0x00007f6efbf37681 in (anonymous namespace)::IconDatabase::iconDatabaseSyncThread (this=0x7f6ee2acc000)
    at ../../Source/WebKit/UIProcess/API/glib/IconDatabase.cpp:953
        __PRETTY_FUNCTION__ = "void WebKit::IconDatabase::iconDatabaseSyncThread()"
        startTime = 3006.9423579999998
        journalFilename = {m_impl = {static isRefPtr = <optimized out>, 
            m_ptr = 0x7f6ee2aca000}}
        timeStamp = 3006.9435509999998
        newStamp = 3006.9436879999998
#19 0x00007f6efbf33a59 in (anonymous namespace)::IconDatabase::<lambda()>::operator()(void) const (__closure=0x7f6ee2af8098)
    at ../../Source/WebKit/UIProcess/API/glib/IconDatabase.cpp:224
        this = 0x7f6ee2acc000
#20 0x00007f6efbf3f6c8 in WTF::Function<void()>::CallableWrapper<WebKit::IconDatabase::open(const WTF::String&, const WTF::String&)::<lambda()> >::call(void) (
    this=0x7f6ee2af8090) at ../../Source/WTF/wtf/Function.h:102
No locals.
#21 0x00007f6efb94cb2b in WTF::Function<void()>::operator()(void) const (
    this=0x7f6e92a9eb20) at ../../Source/WTF/wtf/Function.h:56
No locals.
#22 0x00007f6ef51383de in WTF::threadEntryPoint (contextData=0x7f6ee2af44d0)
    at ../../Source/WTF/wtf/Threading.cpp:101
        context = 0x7f6ee2af44d0
        entryPoint = {
          m_callableWrapper = std::unique_ptr<WTF::Function<void()>::CallableWrapperBase> containing 0x7f6ee2af8090}
#23 0x00007f6ef5178314 in WTF::wtfThreadEntryPoint (param=0x7f6ee2afe0c0)
    at ../../Source/WTF/wtf/ThreadingPthreads.cpp:209
        invocation = std::unique_ptr<WTF::ThreadFunctionInvocation> containing 0x7f6ee2afe0c0
#24 0x00007f6ef105d36d in start_thread (arg=0x7f6e92a9f700)
    at pthread_create.c:456
        __res = <optimized out>
        pd = 0x7f6e92a9f700
        now = <optimized out>
        unwind_buf = {cancel_jmp_buf = {{jmp_buf = {140112883742464, 
                4941255678535664290, 0, 140733047339136, 140112883743168, 0, 
                -5021521763199090014, -5021724863860047198}, 
              mask_was_saved = 0}}, priv = {pad = {0x0, 0x0, 0x0, 0x0}, 
            data = {prev = 0x0, cleanup = 0x0, canceltype = 0}}}
        not_first_call = <optimized out>
        pagesize_m1 = <optimized out>
        sp = <optimized out>
        freesize = <optimized out>
        __PRETTY_FUNCTION__ = "start_thread"
#25 0x00007f6f03b59b8f in clone ()
    at ../sysdeps/unix/sysv/linux/x86_64/clone.S:97
No locals.
Comment 1 Michael Catanzaro 2017-07-23 07:25:02 PDT
(In reply to Michael Catanzaro from comment #0)
> Now, right click on any page and click Save As. The UI process will crash.
> (This might be two different bugs.)

Actually you don't need to do anything. Just load any page. It will hit that crash.
Comment 2 Brady Eidson 2017-07-23 10:18:17 PDT
The assertion in the ~TimerBase destructor is:
    ASSERT(canAccessThreadLocalDataForThread(m_thread));

So a Timer is getting created on one thread but destroyed on another thread.

It's not immediately clear to me how my recent changes changed this.
Comment 3 Brady Eidson 2017-07-23 10:19:28 PDT
That said, this is the sync thread, and it's super surprising to see IconRecords destroyed (and therefore WebCore::Images destroyed) on a background thread.

That's definitely not okay.
Comment 4 Carlos Garcia Campos 2017-07-24 00:57:07 PDT
I think this problem has always existed, but before removing the code, history items were retaining icons preventing them from being deleted in some cases. IconRecord and PageURLRecord objects can be created and destroyed either in sync or main thread. The problem seems to be the frame timer of the BitmapImage, that is not even used nor needed at all. We currently retain icons when they are returned by webkit_favicon_database_get_favicon(), but we release them if we fail to get them. I guess this crash happens for a page that doesn't have a favicon. I don't think it's worth trying to fix the IconDatabase mess, because we will eventually replace it, hopefully during the next cycle. So, for now, I think we can simple change IconRecord::setImageData() to not create the image if the given data is nullptr.
Comment 5 Carlos Garcia Campos 2017-07-24 01:11:20 PDT
Created attachment 316273 [details]
Patch

Could you try this patch, Michael?
Comment 6 Build Bot 2017-07-24 01:13:59 PDT
Thanks for the patch. If this patch contains new public API please make sure it follows the guidelines for new WebKit2 GTK+ API. See http://trac.webkit.org/wiki/WebKitGTK/AddingNewWebKit2API
Comment 7 Michael Catanzaro 2017-07-24 07:56:07 PDT
(In reply to Carlos Garcia Campos from comment #4)
> I don't think it's worth trying to fix the IconDatabase mess, because we will
> eventually replace it, hopefully during the next cycle.

I'd be interested in seeing a plan for this.
Comment 8 Michael Catanzaro 2017-07-24 08:04:23 PDT
Comment on attachment 316273 [details]
Patch

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

I'm not sure I understand this fix. Is your goal to prevent the crash by ensuring that IconDatabase::performReleaseIconForPageURL is never called ever? That is quite a hack, but I think that's fine as you say you're planning to delete all this code, and I'm confident that will happen sooner rather than later. The IconDatabase has always been a mess anyway.

I will test the change to see if it works... building now.

> Source/WebKit/UIProcess/API/glib/IconDatabase.cpp:123
>      // It's okay to delete the raw image here. Any existing clients using this icon will be
>      // managing an image that was created with a copy of this raw image data.

Um... I'm not sure if this comment is really supposed to be in this function at all... but I would have added your new conditional above it rather than below it.
Comment 9 Carlos Garcia Campos 2017-07-24 08:21:48 PDT
(In reply to Michael Catanzaro from comment #7)
> (In reply to Carlos Garcia Campos from comment #4)
> > I don't think it's worth trying to fix the IconDatabase mess, because we will
> > eventually replace it, hopefully during the next cycle.
> 
> I'd be interested in seeing a plan for this.

The plan is to use a new database format that supports multiple icons and sizes per page URL, and modernize and simplify the code.
Comment 10 Carlos Garcia Campos 2017-07-24 08:25:29 PDT
(In reply to Michael Catanzaro from comment #8)
> Comment on attachment 316273 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=316273&action=review
> 
> I'm not sure I understand this fix. Is your goal to prevent the crash by
> ensuring that IconDatabase::performReleaseIconForPageURL is never called
> ever?

No, but when this is called no Image will be deleted.

> That is quite a hack, but I think that's fine as you say you're
> planning to delete all this code, 

It's a side effect, but the change is good in any case, it avoids creating an image for nothing when the page doesn't have a favicon.

> and I'm confident that will happen sooner
> rather than later.

Not sure how soon it will be, but definitely not in this release cycle.

> The IconDatabase has always been a mess anyway.

Indeed.

> I will test the change to see if it works... building now.

Thanks! I'll make a release tomorrow.

> > Source/WebKit/UIProcess/API/glib/IconDatabase.cpp:123
> >      // It's okay to delete the raw image here. Any existing clients using this icon will be
> >      // managing an image that was created with a copy of this raw image data.
> 
> Um... I'm not sure if this comment is really supposed to be in this function
> at all... but I would have added your new conditional above it rather than
> below it.

No, the data is removed when the image is destroyed, so setting it to nullptr would destroy any previous data.
Comment 11 Michael Catanzaro 2017-07-24 08:47:02 PDT
(In reply to Michael Catanzaro from comment #8)
> I will test the change to see if it works... building now.

Your patch fixes the crash I posted above.

It does not fix this error:

ERROR: Failed to start load for icon at url /favicon.ico
../../Source/WebCore/loader/icon/IconLoader.cpp(82) : void WebCore::IconLoader::startLoading()

I will file a new bug for that.

There is also an icon database crash on exit. I will file a new bug for that, too.
Comment 12 Carlos Garcia Campos 2017-07-24 23:39:40 PDT
Committed r219861: <http://trac.webkit.org/changeset/219861>