Bug 175832 - Introduce a new CompletionHandler type and use it for NetworkDataTaskClient's completion handlers to help catch bugs
Summary: Introduce a new CompletionHandler type and use it for NetworkDataTaskClient's...
Status: RESOLVED FIXED
Alias: None
Product: WebKit
Classification: Unclassified
Component: WebKit2 (show other bugs)
Version: WebKit Nightly Build
Hardware: Unspecified Unspecified
: P2 Normal
Assignee: Chris Dumez
URL:
Keywords: InRadar
Depends on: 175872
Blocks:
  Show dependency treegraph
 
Reported: 2017-08-22 10:49 PDT by Chris Dumez
Modified: 2017-08-22 22:02 PDT (History)
12 users (show)

See Also:


Attachments
Patch (12.31 KB, patch)
2017-08-22 10:52 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff
Patch (19.73 KB, patch)
2017-08-22 15:23 PDT, Chris Dumez
no flags Details | Formatted Diff | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Chris Dumez 2017-08-22 10:49:22 PDT
Make NetworkDataTaskClient completion handlers less error prone by introducing a wrapper for them. This wrapper makes sure that:
1. The completion handler is always called
2. The completion handler is only called once

We've been caught by this several times in the past and it causes hard to diagnose issues such as memory leaks and network load hangs.
Comment 1 Alex Christensen 2017-08-22 10:51:25 PDT
We should do this for a lot of things.
Comment 2 Chris Dumez 2017-08-22 10:52:22 PDT
Created attachment 318768 [details]
Patch
Comment 3 Alex Christensen 2017-08-22 10:58:11 PDT
Comment on attachment 318768 [details]
Patch

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

I think we should solve this problem instead by just making a wrapper of WTF::Function that counts how many times it's called in a debug build and asserts that it is called exactly once before it is destroyed

> Source/WebKit/NetworkProcess/NetworkDataTask.h:66
> +    NetworkCompletionHandler(HandlerType&& handler, WTF::Function<void(HandlerType&)>&& defaultHandler)

This is strange.

> Source/WebKit/NetworkProcess/PingLoad.cpp:-108
> -        completionHandler({ });

I think we should keep these in.

> Source/WebKit/NetworkProcess/capture/NetworkDataTaskReplay.cpp:206
> +    RedirectCompletionHandler handler = makeRedirectCompletionHandler([this, protectedThis = makeRef(*this)] (const WebCore::ResourceRequest& updatedRequest) {

auto redirectCompletionHandler
Comment 4 Chris Dumez 2017-08-22 11:01:17 PDT
Comment on attachment 318768 [details]
Patch

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

> Source/WebKit/NetworkProcess/NetworkLoad.cpp:-138
> -    if (m_redirectCompletionHandler)

You really think we should keep these? This is super ugly. Adding assertion will not necessarily help in edge / rare cases because they will not be hit and we will not find the bugs. I'd rather make this less error prone.
Comment 5 Chris Dumez 2017-08-22 11:02:40 PDT
Comment on attachment 318768 [details]
Patch

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

>> Source/WebKit/NetworkProcess/NetworkDataTask.h:66
>> +    NetworkCompletionHandler(HandlerType&& handler, WTF::Function<void(HandlerType&)>&& defaultHandler)
> 
> This is strange.

Maybe we can clarify the naming but I think it makes sense to have a completion handler with default handling if the client does not call it.
Comment 6 Chris Dumez 2017-08-22 11:11:44 PDT
(In reply to Chris Dumez from comment #4)
> Comment on attachment 318768 [details]
> Patch
> 
> View in context:
> https://bugs.webkit.org/attachment.cgi?id=318768&action=review
> 
> > Source/WebKit/NetworkProcess/NetworkLoad.cpp:-138
> > -    if (m_redirectCompletionHandler)
> 
> You really think we should keep these? This is super ugly. Adding assertion
> will not necessarily help in edge / rare cases because they will not be hit
> and we will not find the bugs. I'd rather make this less error prone.

To be clear, these completion handlers happen in case of redirects and authentication which are not common cases. It is very easy to introduce a bug where the redirect / authentication handlers do not call the completion handler, especially in specific error handling code path. Those do not have good test coverage and are not easy to test for. Therefore, I think merely adding assertion is not going to be sufficient to find bugs. Also, this leads to some ugly code where you have to make sure you call completion handler in class destructors.
Comment 7 Chris Dumez 2017-08-22 15:23:00 PDT
Created attachment 318809 [details]
Patch
Comment 8 WebKit Commit Bot 2017-08-22 17:09:43 PDT
Comment on attachment 318809 [details]
Patch

Clearing flags on attachment: 318809

Committed r221059: <http://trac.webkit.org/changeset/221059>
Comment 9 WebKit Commit Bot 2017-08-22 17:09:45 PDT
All reviewed patches have been landed.  Closing bug.
Comment 10 Radar WebKit Bug Importer 2017-08-22 17:10:33 PDT
<rdar://problem/34025346>
Comment 11 Daniel Bates 2017-08-22 20:24:24 PDT
Comment on attachment 318809 [details]
Patch

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

> Source/WebKit/NetworkProcess/NetworkDataTask.cpp:106
> +            completionHandler({ });

This will pass PolicyAction::PolicyUse to the completion handler. Is this intentional?
Comment 12 Chris Dumez 2017-08-22 21:02:22 PDT
Comment on attachment 318809 [details]
Patch

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

>> Source/WebKit/NetworkProcess/NetworkDataTask.cpp:106
>> +            completionHandler({ });
> 
> This will pass PolicyAction::PolicyUse to the completion handler. Is this intentional?

Good catch. This is not intentional. I'll follow-up.
Comment 13 Daniel Bates 2017-08-22 22:02:45 PDT
Comment on attachment 318809 [details]
Patch

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

>>> Source/WebKit/NetworkProcess/NetworkDataTask.cpp:106
>>> +            completionHandler({ });
>> 
>> This will pass PolicyAction::PolicyUse to the completion handler. Is this intentional?
> 
> Good catch. This is not intentional. I'll follow-up.

What about the ordering of calling the completion handler with respect to calling cancel()? Is it acceptable to call the completion handler first?