Closed
Bug 722033
Opened 13 years ago
Closed 13 years ago
Remove calls to synchronous openCacheEntry in nsHttpChannel
Categories
(Core :: Networking: Cache, defect, P1)
Core
Networking: Cache
Tracking
()
RESOLVED
FIXED
mozilla14
People
(Reporter: briansmith, Assigned: michal)
References
(Blocks 1 open bug)
Details
(Keywords: main-thread-io, perf, Whiteboard: [Snappy:P1])
Attachments
(3 files, 7 obsolete files)
18.14 KB,
patch
|
mayhemer
:
review+
jaas
:
superreview+
|
Details | Diff | Splinter Review |
17.42 KB,
patch
|
jaas
:
superreview+
|
Details | Diff | Splinter Review |
14.80 KB,
patch
|
jaas
:
superreview+
|
Details | Diff | Splinter Review |
+++ This bug was initially created as a clone of Bug #695399 +++
Synchronous openCacheEntry takes the cache service lock, and that lock can block on disk I/O, so we cannot call it from the main thread, including anywhere in nsHttpChannel.
Reporter | ||
Updated•13 years ago
|
Blocks: CVE-2011-0082
Reporter | ||
Comment 1•13 years ago
|
||
This is blocking P1 work in PSM and it is blocking bugs that likely need to be fixed to keep the disk cache enabled on mobile. I am going to take a stab at it.
Assignee: nobody → bsmith
Priority: P2 → P1
Assignee | ||
Updated•13 years ago
|
Assignee: bsmith → michal.novotny
Updated•13 years ago
|
Whiteboard: [Snappy] → [Snappy:P1]
Reporter | ||
Comment 2•13 years ago
|
||
Michal, do you have anything that I start testing here? I would like to build my patches on top of this one, even if the changes to the tests are not ready.
Assignee | ||
Comment 3•13 years ago
|
||
(In reply to Brian Smith (:bsmith) from comment #2)
> Michal, do you have anything that I start testing here? I would like to
> build my patches on top of this one, even if the changes to the tests are
> not ready.
What exactly do you need for testing? BTW changing tests is not a scope of this bug and will be covered by bug #695399.
So far I have eliminated openCacheEntry() that is needed due to LOAD_BYPASS_LOCAL_CACHE_IF_BUSY flag, but the patch break some xpc-tests and I'm now trying to find out what's wrong.
Assignee | ||
Comment 4•13 years ago
|
||
- adds blocking argument to nsICacheSession::asyncOpenCacheEntry()
- removes OpenCacheEntry() needed due to LOAD_BYPASS_LOCAL_CACHE_IF_BUSY flag
Attachment #601097 -
Flags: review?(honzab.moz)
Assignee | ||
Comment 5•13 years ago
|
||
This patch should be applied on the top of patch #601097.
Attachment #601099 -
Flags: review?(honzab.moz)
Comment 6•13 years ago
|
||
I'll publish the reviews probably tomorrow.
Comment 7•13 years ago
|
||
Has this been pushed to try?
Comment 8•13 years ago
|
||
Comment on attachment 601097 [details] [diff] [review]
patch 1
Review of attachment 601097 [details] [diff] [review]:
-----------------------------------------------------------------
r=honzab
I think this is correct.
I'd love to find some way to completely avoid duplication of code at http://hg.mozilla.org/mozilla-central/annotate/343ec916dfd5/netwerk/protocol/http/nsHttpChannel.cpp#l249.
::: netwerk/cache/nsCacheService.cpp
@@ +1021,5 @@
> nsnull);
>
> // Don't delete the request if it was queued
> + if (!(mRequest->IsBlocking() &&
> + rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION))
May be more readable as:
!mRequest-IsBlocking() ||
rv != NS_ERROR_CACHE_WAIT_FOR_VALIDATION
@@ +1669,5 @@
> + if (request->IsBlocking()) {
> + // async exits - validate, doom, or close will resume
> + return rv;
> + }
> + } else if (request->IsBlocking()) {
As I understand, a non-blocking request is intended to give up when the cache entry can't be opened (from whatever reason) and to cancel the |open| operation, right?
However blocking ones are intended to always try to open the cache entry even on WAIT_FOR_VALIDATION (either synchronously through WaitForValidation() or asynchronously via callback), is that so?
I think for simplicity the condition may just be:
if (blocking) {
if (listener)
return rv;
WaitForValidation();
}
@@ +1777,5 @@
> rv = gService->ProcessRequest(request, true, result);
>
> // delete requests that have completed
> + if (!(listener && blockingMode &&
> + (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION)))
Perhaps the same here (! || ! || !)...
Non-blocking requests are done here according my previous comment, right?
Please also check whether to delete requests in nsCacheService::ProcessPendingRequests also when the request is non-blocking. I think you should since non-blocking async requests may return NS_ERROR_CACHE_WAIT_FOR_VALIDATION. I actually think the condition should be the same as are now here.
::: netwerk/cache/nsICacheSession.idl
@@ +81,5 @@
> * available.
> */
> void asyncOpenCacheEntry(in ACString key,
> in nsCacheAccessMode accessRequested,
> + in boolean blockingMode,
Also update the documentation.
::: netwerk/protocol/http/nsHttpChannel.cpp
@@ +2255,5 @@
> + accessRequested,
> + !(mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY),
> + this);
> +
> + if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) {
Can you ever get this error here regardless blocking or non-blocking request? I think the state needed to determine this error result is processed only asynchronously on the cache thread, right?
Attachment #601097 -
Flags: review?(honzab.moz) → review+
Comment 9•13 years ago
|
||
Comment on attachment 601099 [details] [diff] [review]
patch 2 - removes OpenCacheEntry() in OpenOfflineCacheEntryForWriting()
Review of attachment 601099 [details] [diff] [review]:
-----------------------------------------------------------------
If there were anything wrong with the changes then tests should catch it. I don't want to stare in to the patch too long, it proved to be useless.
r=honzab
However, both reviews are conditioned by an as-much-as-possible-green try run (I'm going to push it right now).
::: netwerk/protocol/http/nsHttpChannel.cpp
@@ +2258,5 @@
> LOG(("bypassing local cache since it is busy\n"));
> rv = NS_ERROR_NOT_AVAILABLE;
> }
>
> + if (NS_SUCCEEDED(rv)) return NS_OK;
return on a new line please.
@@ +2349,5 @@
> // access to the cache entry has been denied (because the cache entry
> // is probably in use by another channel). Either the cache is being
> // read from (we're offline) or it's being updated elsewhere.
> return NS_OK;
> }
Can we ever get this result from AsyncOpenCacheEntry ?
@@ +2354,5 @@
>
> + if (NS_SUCCEEDED(rv))
> + return NS_OK;
> +
> + return rv;
Just return rv?
@@ +4890,5 @@
> + return NS_OK;
> + }
> +
> + if (NS_FAILED(rv))
> + return rv;
Could we potentially do this in parallel? (In a follow-up, though a helper class probably)
Attachment #601099 -
Flags: review?(honzab.moz) → review+
Comment 10•13 years ago
|
||
Updated•13 years ago
|
Attachment #601097 -
Flags: review+
Comment 11•13 years ago
|
||
Comment on attachment 601099 [details] [diff] [review]
patch 2 - removes OpenCacheEntry() in OpenOfflineCacheEntryForWriting()
There is a consistent M(oth) tests failure.
Attachment #601099 -
Flags: review+
Comment 12•13 years ago
|
||
Assignee | ||
Comment 13•13 years ago
|
||
(In reply to Honza Bambas (:mayhemer) from comment #8)
> I'd love to find some way to completely avoid duplication of code at
> http://hg.mozilla.org/mozilla-central/annotate/343ec916dfd5/netwerk/protocol/
> http/nsHttpChannel.cpp#l249.
I agree, but I would prefer to do this in a follow-up bug.
> > // Don't delete the request if it was queued
> > + if (!(mRequest->IsBlocking() &&
> > + rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION))
>
> May be more readable as:
>
> !mRequest-IsBlocking() ||
> rv != NS_ERROR_CACHE_WAIT_FOR_VALIDATION
I think that negation of conjunction is easier to understand than disjunction of negation. But if others have the same opinion as you, I can change it.
> As I understand, a non-blocking request is intended to give up when the
> cache entry can't be opened (from whatever reason) and to cancel the |open|
> operation, right?
>
> However blocking ones are intended to always try to open the cache entry
> even on WAIT_FOR_VALIDATION (either synchronously through
> WaitForValidation() or asynchronously via callback), is that so?
Correct.
> I think for simplicity the condition may just be:
> if (blocking) {
> if (listener)
> return rv;
>
> WaitForValidation();
> }
Right, this is easier to read. Fixed.
> @@ +1777,5 @@
> > rv = gService->ProcessRequest(request, true, result);
> >
> > // delete requests that have completed
> > + if (!(listener && blockingMode &&
> > + (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION)))
>
> Perhaps the same here (! || ! || !)...
The same as above...
> Non-blocking requests are done here according my previous comment, right?
>
>
> Please also check whether to delete requests in
> nsCacheService::ProcessPendingRequests also when the request is
> non-blocking. I think you should since non-blocking async requests may
> return NS_ERROR_CACHE_WAIT_FOR_VALIDATION. I actually think the condition
> should be the same as are now here.
I don't think so. We should never end up processing a non-blocking request in nsCacheService::ProcessPendingRequests() since it is never queued.
> ::: netwerk/cache/nsICacheSession.idl
> @@ +81,5 @@
> > * available.
> > */
> > void asyncOpenCacheEntry(in ACString key,
> > in nsCacheAccessMode accessRequested,
> > + in boolean blockingMode,
>
> Also update the documentation.
I've updated the description in idl and I'll update MDN after landing this patch.
> ::: netwerk/protocol/http/nsHttpChannel.cpp
> @@ +2255,5 @@
> > + accessRequested,
> > + !(mLoadFlags & LOAD_BYPASS_LOCAL_CACHE_IF_BUSY),
> > + this);
> > +
> > + if (rv == NS_ERROR_CACHE_WAIT_FOR_VALIDATION) {
>
> Can you ever get this error here regardless blocking or non-blocking
> request? I think the state needed to determine this error result is
> processed only asynchronously on the cache thread, right?
Right, AsyncOpenCacheEntry() never returns NS_ERROR_CACHE_WAIT_FOR_VALIDATION. Fixed.
> There is a consistent M(oth) tests failure.
Fixed.
Attachment #601097 -
Attachment is obsolete: true
Attachment #603215 -
Flags: review?(honzab.moz)
Assignee | ||
Comment 14•13 years ago
|
||
(In reply to Honza Bambas (:mayhemer) from comment #9)
> @@ +4890,5 @@
> > + return NS_OK;
> > + }
> > +
> > + if (NS_FAILED(rv))
> > + return rv;
>
> Could we potentially do this in parallel? (In a follow-up, though a helper
> class probably)
Do you mean to do OpenOfflineCacheEntryForWriting() and OpenNormalCacheEntry() in parallel? It should be possible, but it is definitely out of scope of this bug.
Attachment #601099 -
Attachment is obsolete: true
Attachment #603216 -
Flags: review?(honzab.moz)
Assignee | ||
Comment 15•13 years ago
|
||
pushed to try server
https://tbpl.mozilla.org/?tree=Try&rev=861d85480e00
Comment 16•13 years ago
|
||
(In reply to Michal Novotny (:michal) from comment #13)
> I agree, but I would prefer to do this in a follow-up bug.
Definitely. Can you please file it?
> I think that negation of conjunction is easier to understand than
> disjunction of negation. But if others have the same opinion as you, I can
> change it.
I perceive simpler to see that when just one condition doesn't apply and the code executes. But up to you.
> I don't think so. We should never end up processing a non-blocking request
> in nsCacheService::ProcessPendingRequests() since it is never queued.
Then it's OK. Maybe worth a comment?
(In reply to Michal Novotny (:michal) from comment #14)
> Do you mean to do OpenOfflineCacheEntryForWriting() and
> OpenNormalCacheEntry() in parallel? It should be possible, but it is
> definitely out of scope of this bug.
I don't think this is worth to fix, actually... It may just have a minor affect on background offline cache loads.
Comment 17•13 years ago
|
||
Comment on attachment 603215 [details] [diff] [review]
part1 v2
Review of attachment 603215 [details] [diff] [review]:
-----------------------------------------------------------------
As I understand today discussion during the meeting, you will update the IDL ones more, right? This patch looks good, but I think I should review the final one ones more.
So, preliminary r+, I'll take a quick look at the final patch.
Attachment #603215 -
Flags: review?(honzab.moz)
Comment 18•13 years ago
|
||
Comment on attachment 603216 [details] [diff] [review]
part2 v2 - fixed according to comment #9
Review of attachment 603216 [details] [diff] [review]:
-----------------------------------------------------------------
Looks good, r+, but the same as the previous patch.
Attachment #603216 -
Flags: review?(honzab.moz)
Assignee | ||
Comment 19•13 years ago
|
||
Attachment #603215 -
Attachment is obsolete: true
Attachment #605603 -
Flags: review?(honzab.moz)
Assignee | ||
Comment 20•13 years ago
|
||
Attachment #603216 -
Attachment is obsolete: true
Attachment #605604 -
Flags: review?(honzab.moz)
Assignee | ||
Comment 21•13 years ago
|
||
This patch removes the last openCacheEntry() in nsHttpChannel that is used to find and invalidate an entry.
Attachment #605605 -
Flags: review?(honzab.moz)
Assignee | ||
Comment 22•13 years ago
|
||
pushed to tryserver: https://tbpl.mozilla.org/?tree=Try&rev=db932be8e043
Assignee | ||
Comment 23•13 years ago
|
||
(In reply to Honza Bambas (:mayhemer) from comment #16)
> (In reply to Michal Novotny (:michal) from comment #13)
> > I agree, but I would prefer to do this in a follow-up bug.
>
> Definitely. Can you please file it?
Bug #735538
Comment 24•13 years ago
|
||
Comment on attachment 605603 [details] [diff] [review]
part1 v3 - the new argument of the asyncOpenCacheEntry() is now optional
Review of attachment 605603 [details] [diff] [review]:
-----------------------------------------------------------------
r=honzab
::: netwerk/cache/nsICacheSession.idl
@@ +77,5 @@
>
> /**
> + * Asynchronous cache access. Does not block the calling thread. Instead,
> + * the listener will be notified when the descriptor is available. If
> + * 'noWait' is set to true, the listener will be notified immediately with
s/will be/is/ I think..
Attachment #605603 -
Flags: review?(honzab.moz) → review+
Comment 25•13 years ago
|
||
Comment on attachment 605604 [details] [diff] [review]
part2 v3
Review of attachment 605604 [details] [diff] [review]:
-----------------------------------------------------------------
r=honzab
Attachment #605604 -
Flags: review?(honzab.moz) → review+
Comment 26•13 years ago
|
||
Comment on attachment 605605 [details] [diff] [review]
part3
Review of attachment 605605 [details] [diff] [review]:
-----------------------------------------------------------------
r=honzab with comments addressed and after this passes try.
::: netwerk/cache/nsCacheService.cpp
@@ +1053,5 @@
> + return NS_OK;
> + }
> +
> +private:
> + nsICacheListener *mListener;
nsCOMPtr, see more bellow.
@@ +1094,5 @@
> + }
> +
> + if (entry) {
> + status = NS_OK;
> + nsCacheService::gService->DoomEntry_Internal(entry, foundActive);
Can this fail?
@@ +1099,5 @@
> + }
> +
> + if (mListener) {
> + mThread->Dispatch(new nsNotifyDoomListener(mListener, status),
> + NS_DISPATCH_NORMAL);
nsRefPtr for nsNotifyDoomListener object please.
@@ +1110,5 @@
> +
> +private:
> + nsCString mKey;
> + nsCacheStoragePolicy mStoragePolicy;
> + nsICacheListener *mListener;
We leak the listener when dispatch of this event fails. This has to be nsCOMPtr. You can swap it to nsNotifyDoomListener event with dont_AddRef and forget() this one.
@@ +1111,5 @@
> +private:
> + nsCString mKey;
> + nsCacheStoragePolicy mStoragePolicy;
> + nsICacheListener *mListener;
> + nsCOMPtr<nsIThread> mThread;
Would nsIEventTarget be enough here?
@@ +1442,5 @@
> +
> + if (!gService->mInitialized)
> + return NS_ERROR_NOT_INITIALIZED;
> +
> + return DispatchToCacheIOThread(new nsDoomEvent(session, key, listener));
Please preserve this style of dispatching:
http://hg.mozilla.org/mozilla-central/annotate/78e56fd22f2a/netwerk/cache/nsCacheService.cpp#l1762
::: netwerk/protocol/http/nsHttpChannel.cpp
@@ +5213,5 @@
>
> if (NS_FAILED(rv))
> return;
>
> + session->DoomEntry(key, nsnull);
Shouldn't DoInvalidateCacheEntry be renamed to DoomCacheEntry or so?
::: netwerk/test/unit/test_doomentry.js
@@ +18,5 @@
> + return _CSvc = Cc["@mozilla.org/network/cache-service;1"].
> + getService(Ci.nsICacheService);
> +}
> +
> +function get_ostream(key, asFile, append, callback)
Hint: objects should be UpperCamelCase to be easily recognized from functions.
@@ +156,5 @@
> +
> +function check_doom4(status)
> +{
> + do_check_eq(status, Cr.NS_ERROR_NOT_AVAILABLE);
> + do_test_finished();
Should you rather clear the cache here?
Attachment #605605 -
Flags: review?(honzab.moz) → review+
Assignee | ||
Comment 27•13 years ago
|
||
(In reply to Honza Bambas (:mayhemer) from comment #26)
> ::: netwerk/cache/nsCacheService.cpp
> > +private:
> > + nsICacheListener *mListener;
>
> nsCOMPtr, see more bellow.
>
>
> > + nsICacheListener *mListener;
>
> We leak the listener when dispatch of this event fails. This has to be
> nsCOMPtr. You can swap it to nsNotifyDoomListener event with dont_AddRef
> and forget() this one.
The leak in case of failure is intentional since we need to release the listener on the callers thread. If we can't post the event to the correct thread how we could release the reference on the same thread? BTW we do the same in nsCacheService::NotifyListener().
> @@ +1111,5 @@
> > +private:
> > + nsCString mKey;
> > + nsCacheStoragePolicy mStoragePolicy;
> > + nsICacheListener *mListener;
> > + nsCOMPtr<nsIThread> mThread;
>
> Would nsIEventTarget be enough here?
It would, but what's the benefit? do_GetCurrentThread returns already_AddRefed<nsIThread>.
> > + mThread->Dispatch(new nsNotifyDoomListener(mListener, status),
> > + NS_DISPATCH_NORMAL);
>
> nsRefPtr for nsNotifyDoomListener object please.
>
>
> > + return DispatchToCacheIOThread(new nsDoomEvent(session, key, listener));
>
> Please preserve this style of dispatching:
>
> http://hg.mozilla.org/mozilla-central/annotate/78e56fd22f2a/netwerk/cache/
> nsCacheService.cpp#l1762
It's actually a relict from times when new could fail. And this style is also present in the cache code, e.g. http://hg.mozilla.org/mozilla-central/annotate/78e56fd22f2a/netwerk/cache/nsDiskCacheDevice.cpp#l1141.
> ::: netwerk/protocol/http/nsHttpChannel.cpp
> @@ +5213,5 @@
> >
> > if (NS_FAILED(rv))
> > return;
> >
> > + session->DoomEntry(key, nsnull);
>
> Shouldn't DoInvalidateCacheEntry be renamed to DoomCacheEntry or so?
I don't think it's necessary. Both dooming the entry as well as setting expiration time to 0 do invalidate the entry.
> ::: netwerk/test/unit/test_doomentry.js
> @@ +18,5 @@
> > + return _CSvc = Cc["@mozilla.org/network/cache-service;1"].
> > + getService(Ci.nsICacheService);
> > +}
> > +
> > +function get_ostream(key, asFile, append, callback)
>
> Hint: objects should be UpperCamelCase to be easily recognized from
> functions.
Renamed.
> @@ +156,5 @@
> > +
> > +function check_doom4(status)
> > +{
> > + do_check_eq(status, Cr.NS_ERROR_NOT_AVAILABLE);
> > + do_test_finished();
>
> Should you rather clear the cache here?
A common rule is to clean the cache before running the test rather than rely on cleanup performed by previous test.
Attachment #605605 -
Attachment is obsolete: true
Comment 28•13 years ago
|
||
(In reply to Michal Novotny (:michal) from comment #27)
> The leak in case of failure is intentional ... BTW we do the
> same in nsCacheService::NotifyListener().
Ah, I wasn't aware. Maybe just add a comment.
I also agree with the rest. Thanks.
Assignee | ||
Comment 29•13 years ago
|
||
(In reply to Honza Bambas (:mayhemer) from comment #26)
> > + if (entry) {
> > + status = NS_OK;
> > + nsCacheService::gService->DoomEntry_Internal(entry, foundActive);
>
> Can this fail?
I forgot to answer this question. DoomEntry_Internal() returns always NS_OK and I don't think that we'll change this behavior in future.
(In reply to Honza Bambas (:mayhemer) from comment #28)
> (In reply to Michal Novotny (:michal) from comment #27)
> > The leak in case of failure is intentional ... BTW we do the
> > same in nsCacheService::NotifyListener().
>
> Ah, I wasn't aware. Maybe just add a comment.
Comment added.
Pushed to tryserver again because of a strange failure in the last try:
https://tbpl.mozilla.org/?tree=Try&rev=5932f13b5eb4
Attachment #607223 -
Attachment is obsolete: true
Assignee | ||
Comment 30•13 years ago
|
||
not sure if this need a sr
Attachment #605603 -
Attachment is obsolete: true
Attachment #607377 -
Flags: superreview?(joshmoz)
Assignee | ||
Updated•13 years ago
|
Attachment #607269 -
Flags: superreview?(joshmoz)
Assignee | ||
Updated•13 years ago
|
Attachment #605604 -
Flags: superreview?(joshmoz)
Attachment #605604 -
Flags: superreview?(joshmoz) → superreview+
Attachment #607269 -
Flags: superreview?(joshmoz) → superreview+
Attachment #607377 -
Flags: superreview?(joshmoz) → superreview+
Assignee | ||
Comment 31•13 years ago
|
||
http://hg.mozilla.org/integration/mozilla-inbound/rev/6c8d1da1e1db
http://hg.mozilla.org/integration/mozilla-inbound/rev/5b61e3d75735
http://hg.mozilla.org/integration/mozilla-inbound/rev/835ac64631ec
Whiteboard: [Snappy:P1] → [Snappy:P1] [inbound]
Target Milestone: --- → mozilla14
Comment 32•13 years ago
|
||
https://hg.mozilla.org/mozilla-central/rev/6c8d1da1e1db
https://hg.mozilla.org/mozilla-central/rev/5b61e3d75735
https://hg.mozilla.org/mozilla-central/rev/835ac64631ec
Status: NEW → RESOLVED
Closed: 13 years ago
Resolution: --- → FIXED
Whiteboard: [Snappy:P1] [inbound] → [Snappy:P1]
Comment 33•13 years ago
|
||
Fix for the comm-central bustage: http://hg.mozilla.org/comm-central/rev/d2f3b160dd8b
David (cc'ed) may want to review this change after the fact.
You need to log in
before you can comment on or make changes to this bug.
Description
•