Non GC'ed caches keep them from being closed (and also deleted). |
|||
Issue description
A CacheStorage cache that is deleted in JavaScript, via a call to caches.delete() will not result in the cache actually being deleted if there is a prior JavaScript object reference to that cache that has not yet been GC'ed. For example:
caches.open(CACHE_NAME).then(function(cache) { // <= JS reference here.
cache.put(url, response);
});
caches.delete(CACHE_NAME);
In the above code the cache will still exist on disk until a GC happens, the tab is closed, or (if in a Service Worker) the browser is restarted.
,
Nov 8 2017
bkelly@ Yes, you're correct, and we do have tests to verify that a cache isn't deleted until the last reference is closed. However, I think an unfortunate side effect is what is described above. With a service worker many MB's, or even GB's of data can be written to disk without creating enough JS heap use to cause a GC.
,
Nov 8 2017
Ok. If this is about not running GC enough, then sure. I just wanted to make sure we didn't remove the feature of live objects continuing to work after delete() while referenced. Sorry for my confusion.
,
Mar 16 2018
Any update on this bug? It's relatively straightforward to get into a bad situation in Google Docs that prevents docs from getting synced offline due to quota issues.
,
Mar 16 2018
We could consider adding a new method to the spec that immediately invalidates the job wrapper. Something like Cache.disconnect(), etc. This would let you avoid having to wait for GC if your particular site happens to hit this kind of issue. One question, though. How is your site observing that the disk resources are still in use. Storage API? This may be a GC observability issue that needs to be addressed as well.
,
Mar 16 2018
If the mechanism of requiring the data to be stored until the reference is GC'ed is justified, then adding an explicit method would definitely help here. Alternatively, is it also possible for Chrome to schedule a GC run shortly after a delete call happens? We use queryUsageAndQuota() from a page context to figure out the usage.
,
Mar 16 2018
Hmm, ok. That is a non-standard API, but its pretty much the same as Storage API's estimate() for this purpose, though. I filed a spec issue about the GC observability: https://github.com/whatwg/storage/issues/60 I also filed a spec issue for some kind of explicit detach or immediate deletion: https://github.com/w3c/ServiceWorker/issues/1287
,
Mar 16 2018
Would the workaround mentioned in https://bugs.chromium.org/p/chromium/issues/detail?id=777462#c17, also work for this issue? i.e. if we delete all keys before we delete the Cache? Also curious about the motivation for the spec behavior i.e. why should the Cache references still be accessible after a CacheStorage.delete()? https://w3c.github.io/ServiceWorker/#cache-storage-delete
,
Mar 19 2018
It sounds like this might be the same issue as https://crbug.com/795701 ?
,
Mar 19 2018
> Also curious about the motivation for the spec behavior i.e. why should the Cache references still be accessible after a CacheStorage.delete()? Since Cache API does not have transaction support it would be difficult to use any delete operation without this behavior. Separate asynchronous operations (like multiple fetch events) could step on each other. In addition, you really need to hold it alive as long as one of the response bodies is still unconsumed. Consider the case where a `Cache.match()` has resolved a `Response` and passed it to the browser via `FetchEvent.respondWith()`. If deletion was immediate and forceful, then content would not have any idea when it was safe to perform the deletion since it can't tell when the browser finishes consuming the body.
,
Mar 20 2018
Thanks for the explanation. Anyone able to confirm if the workaround mentioned in crbug.com/777462#c17 would work here? Wouldn't deleting the individual entries also be susceptible to the same garbage collection issues?
,
Mar 23 2018
Couldn't you impose a reasonable time-limit (say, an hour?) on leaving a resource around, and then garbage collect it? As long as deleting prevents new reads from cache, then after a time limit you'd expect nobody to still be using a resource unless they're holding onto it in memory for a long time, and then it would be reasonably safe to delete it.
,
Mar 26 2018
We've decided to mitigate this in the interim by deleting the entries ahead of the cache. Of course, it is likely that this workaround will break again once we fix the behavior here, so it would be ideal to implement some mechanism to release this memory eventually (i.e. comment 12) so when that does get fixed we don't end up in this state again.
,
Apr 10 2018
I think we might have misunderstood this bug. Holding a JS reference to a cache prevents it from being garbage collected which prevents it from being deleted from disk. Can anyone clarify: - what it means to "have a JS reference" to a cache? Do local variables count or would you have to have a more permanent reference? - When does the garbage collector run? Will it run while the service worker is still running? To summarize, if you only access cache through local variables, when after deletion can you expect the cache to actually be deleted from disk?
,
Nov 8
This could be worse than expected due to this code: https://cs.chromium.org/chromium/src/content/browser/cache_storage/cache_storage_dispatcher_host.cc?l=364-368&rcl=85f78938e304061d5dea7a5455ffaab5d7881adb Which was added in bug 558427 . I'm planning to remove this timer in bug 902488 . |
|||
►
Sign in to add a comment |
|||
Comment 1 by bke...@mozilla.com
, Nov 8 2017