Bug 101416 - Assertion failure in SubresourceLoader::didFail when reloading
Summary: Assertion failure in SubresourceLoader::didFail when reloading
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: Page Loading (show other bugs)
Version: 528+ (Nightly build)
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Alexey Proskuryakov
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2012-11-06 17:54 PST by KyungTae Kim
Modified: 2013-01-09 12:55 PST (History)
5 users (show)

See Also:


Attachments
Patch (1.69 KB, patch)
2012-11-06 18:03 PST, KyungTae Kim
ap: review-
Details | Formatted Diff | Diff
proposed fix (6.57 KB, patch)
2013-01-09 12:16 PST, Alexey Proskuryakov
japhet: review+
Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description KyungTae Kim 2012-11-06 17:54:53 PST
Crash occurred when SubresourceLoader::didFail called during reload by ASSERT(!m_resource->resourceToRevalidate())
The m_resource->m_resourceToRevalidate was set by CachedResource::setResourceToRevalidate on request,
and was expected to clear by CachedResource::clearResourceToRevalidate when responce received.

CachedResourceLoader::requestResource
 CachedResourceLoader::revalidateResource
  CachedResource::setResourceToRevalidate

SubresourceLoader::didReceiveResponse
 MemoryCache::revalidationSucceeded  (or MemoryCache::revalidationFailed)
  CachedResource::clearResourceToRevalidate

But, when  SubresourceLoader::didFail called by ResourceLoader::didFail, there was no chance to clear before that.
sendRequestCallback
 ResourceLoader::didFail
  SubresourceLoader::didFail

So, in this case, clear the resourceToRevalidate on there would be more suitable than ASSERT.
Comment 1 KyungTae Kim 2012-11-06 18:03:02 PST
Created attachment 172688 [details]
Patch
Comment 2 Nate Chapin 2012-11-07 09:58:28 PST
(In reply to comment #0)
> Crash occurred when SubresourceLoader::didFail called during reload by ASSERT(!m_resource->resourceToRevalidate())
> The m_resource->m_resourceToRevalidate was set by CachedResource::setResourceToRevalidate on request,
> and was expected to clear by CachedResource::clearResourceToRevalidate when responce received.
> 
> CachedResourceLoader::requestResource
>  CachedResourceLoader::revalidateResource
>   CachedResource::setResourceToRevalidate
> 
> SubresourceLoader::didReceiveResponse
>  MemoryCache::revalidationSucceeded  (or MemoryCache::revalidationFailed)
>   CachedResource::clearResourceToRevalidate
> 
> But, when  SubresourceLoader::didFail called by ResourceLoader::didFail, there was no chance to clear before that.
> sendRequestCallback
>  ResourceLoader::didFail
>   SubresourceLoader::didFail
> 
> So, in this case, clear the resourceToRevalidate on there would be more suitable than ASSERT.

Please provide a complete stack trace, and a test case if possible. I don't have enough context from this description to be sure that this is the correct fix.

Thanks!
Comment 3 KyungTae Kim 2012-11-07 15:26:24 PST
I found it on Webkit2 EFL MiniBrowser.
The test case was.. 
1) enter some site - and all the subresource downloaded successfully
2) reload  - and  one of the subresource downloaded failed
3) WebProcess crash occurred by the ASSERT fail

This is rare case, and I couldn't make layout test for that.

The site I found it is :
 http://media.daum.net/photo/5662#20121107080810714
The below subresource didFail when reload :
http://s1.daumcdn.net/photo-media/static/media/3.6.3/dist/media/news_photo.min.css

The backtrace was like the below :

#0  0x00007f82a6ab4485 in WebCore::SubresourceLoader::didFail (this=0x198e870, error=...) at Source/WebCore/loader/SubresourceLoader.cpp:285
#1  0x00007f82a6aaf7bb in WebCore::ResourceLoader::didFail (this=0x198e870, error=...) at Source/WebCore/loader/ResourceLoader.cpp:460
#2  0x00007f82a75f99cc in WebCore::sendRequestCallback (res=0x1cb5420, data=0x1b315b0) at Source/WebCore/platform/network/soup/ResourceHandleSoup.cpp:437
#3  0x00007f82a28aea8d in g_simple_async_result_complete (simple=0x1cb5420) at gsimpleasyncresult.c:767
#4  0x00007f82a23a0676 in http_input_stream_ready_cb (source=0x163c010, result=0x20462e0, user_data=0x17740c0) at soup-request-http.c:139
#5  0x00007f82a28aea8d in g_simple_async_result_complete (simple=0x20462e0) at gsimpleasyncresult.c:767
#6  0x00007f82a23a7fbb in send_request_return_result (stream=<optimized out>, error=<optimized out>, item=<optimized out>) at soup-session-async.c:522
#7  0x00007f82a23a8256 in try_run_until_read (item=0x7f8244003190) at soup-session-async.c:670
#8  0x00007f82a23a826c in read_ready_cb (msg=<optimized out>, user_data=<optimized out>) at soup-session-async.c:644
#9  0x00007f82a2be0e53 in g_main_dispatch (context=0x1780340) at gmain.c:2539
#10 g_main_context_dispatch (context=0x1780340) at gmain.c:3075
#11 0x00007f82a3b3016e in _ecore_glib_select__locked (ecore_timeout=0x1780340, efds=<optimized out>, wfds=<optimized out>, rfds=<optimized out>, ecore_fds=5, ctx=<optimized out>) at ecore_glib.c:171
#12 _ecore_glib_select (ecore_fds=5, rfds=<optimized out>, wfds=<optimized out>, efds=<optimized out>, ecore_timeout=0x1780340) at ecore_glib.c:205
#13 0x00007f82a3b29dc9 in _ecore_main_select (timeout=<optimized out>) at ecore_main.c:1444
#14 0x00007f82a3b2a955 in _ecore_main_loop_iterate_internal (once_only=0) at ecore_main.c:1872
#15 0x00007f82a3b2ac57 in ecore_main_loop_begin () at ecore_main.c:934
#16 0x00007f82a75de5b1 in WebCore::RunLoop::run () at Source/WebCore/platform/efl/RunLoopEfl.cpp:90
#17 0x00007f82aa7cb8b6 in WebKit::WebProcessMainEfl (argc=2, argv=0x7fff9502acf8) at Source/WebKit2/WebProcess/efl/WebProcessMainEfl.cpp:126
#18 0x0000000000400794 in main (argc=2, argv=0x7fff9502acf8) at Source/WebKit2/efl/MainEfl.cpp:30
Comment 4 Nate Chapin 2012-11-07 16:03:34 PST
Hmm, it is pretty rare to have a revalidation attempt trigger didFail() when the original request didn't.

For a reproducible layout test, my first thought is:

Request a subresource, which includes a "Cache-Control: no-store, no-cache, must-revalidate" header.

Request it again, but this time it redirects to http://localhost:7, which should reliably trigger a didFail().

I'm especially curious to know whether this crashes happens on all ports. I can't tell from inspection whether sendRequestCallback() is calling didFail() at the correct time.
Comment 5 Alexey Proskuryakov 2012-11-07 16:05:36 PST
> Hmm, it is pretty rare to have a revalidation attempt trigger didFail() when the original request didn't.

Probably occurs when network is down. We have a "network down" simulating script somewhere in http/tests for testing applications cache. It might help here, too.
Comment 6 Alexey Proskuryakov 2012-11-07 16:06:19 PST
Comment on attachment 172688 [details]
Patch

r- for the lack of a test case.
Comment 7 Alexey Proskuryakov 2013-01-09 12:16:00 PST
Created attachment 181966 [details]
proposed fix
Comment 8 Alexey Proskuryakov 2013-01-09 12:55:16 PST
Committed <http://trac.webkit.org/changeset/139230>.