Issue metadata
Sign in to add a comment
|
Cancellation in ResourceHandler/ResourceThrottle stack is broken |
||||||||||||||||||||||||
Issue descriptionResourceHandlers / ResourceThrottles are supposed to cancel requests by either: 1) Synchronously returning false. 2) Calling ResourceController asynchronously. ResourceLoader is not designed for ResourceController::Cancel / CancelWithError to be invoked synchronously and either true or false to be returned, or URLRequest::Cancel to be called (Synchronously or asynchronously), yet we have ResourceHandlers and ResourceThrottles that do both of these...And things *seem* to work when this is done, but there's no code to explicitly support either of these cases. We should fix this. Seems like we a couple options: 1) Make ResourceController::Cancel the only way to cancel requests, allowing synchronous invocation, and get rid of the return value. 2) Enforce that ResourceController::Cancel isn't called synchronously. We could try and get fancy, and make it nullptr when it can't be called, but given how we create stacks of ResourceHandlers that share a ResourceController, that probably won't work too well. Note that unless we change the return value to a net::Error instad of a bool, this path will preclude us from failing synchronously with custom error codes, which seems bad, unless we want to remove that ability completely - Looks like we only use 4 error codes with CAncelWithError: ERR_TEMPORARILY_THROTTLED, ERR_INSUFFICIENT_RESOURCES, and ERR_BLOCKED_BY_CLIENT, and ERR_FAILED. 3) Make sending cancel signals sent via both paths at once work. This just seems like a bad idea to me. This issue is a bit related to issue 472771 , which aims to reword URLRequest::Cancel semantics. Getting rid of URLRequest::Cancel, for instance, would protect against subclasses incorrectly calling URLRequestCancel instead of ResourceController::Cancel or returning false.
,
Sep 29 2016
Getting rid of the bool should be trivial...URLRequest::Cancel is more complicated. I'd really like to remove URLRequest::Cancel, but I'm not sure that's feasible (See issue 472771 for more discussion). Allowing sync invocation is a little weird - ResourceLoader then becomes a bit of a push/pull dongle, but shouldn't be too hard...Though we'd need to update MimeTypeResourceHandler in the same manner.
,
Sep 29 2016
Another issue is that classes should only be calling Cancel when it's their turn. If they don't, it could be another class's turn with the request...and things devolve from there quickly.
,
Oct 12 2016
Another fun case: Something cancels a request while one handler has it deferred. The cancel is deferred before it reaches that handler, and then that handler tries to resume the request. Reasoning about whether this case explodes, kinda works, mostly works, sorta works, or does in fact work is left as an exercise for the reader, but we don't have explicit handling of it.
,
Oct 24 2016
So one of the biggest problems seems to be: ResourceHandler A calls Cancel() out of turn. ResourceHandler B then calls Cancel()/Resume() in turn/out of turn. We could either end up with two Cancels() making their way through the stack, or think the Resume() is for something deferring the OnRequestComplete call initiated by the cancel, or possibly run into a DCHECK in ResourceLoader::Resume (Which is actually probably safe, but doesn't seem great). Individual ResourceHandler types that subclass ResourceHandler could also have a Cancel and Resume hanging out in their control flow as the same time as well, which could lead to similar issues. Seems like the easiest two ways to fix this would be to either: 1) Forbid cancelling/failing a request out of turn. This doesn't work, since the AsyncResourceHandler can cancel at any point. 2) Forbid delaying cancellation. RedirectToFileResourceHandler really wants to do that, unclear if we'd break anything if we changed that. On error, it would mean the renderer may not get all of a partially retrieved body. Other options: 3) Defer cancellation if it comes out of turn, until it's the cancellee's turn. We don't know when it's the cancellee's turn, which makes this a little problematic. I suppose we could give things a null ResourceController until it's their turn, but doesn't seem great. 4) Have things able to peek at the ResourceLoader's real status (Cancelled or not). This...works, but really doesn't scale, since everything would then be responsible for its own safety. I'm kinda low on ideas here, I'm just concerned that the entire ResourceHandler stack is a mess, and has a number of hard edges around cancellation.
,
Oct 25 2016
Merging into new issues with simpler description of problem. |
|||||||||||||||||||||||||
►
Sign in to add a comment |
|||||||||||||||||||||||||
Comment 1 by csharrison@chromium.org
, Sep 29 2016