Problem/Motivation
The logic in _views_fetch_data() is erroneous:
Call-stack to create issue:
- Call
_views_fetch_data('table_a')using a table. - Call
_views_fetch_data('table_b')using a table. - Now the static cache (
$cache) in_views_fetch_data()will contain those two tables - Now call
_views_fetch_data()without a table. And imagine the main cache entry was deleted from the cache earlier (e.g. Redis LRU / memcache cache item eviction).
Here's what_views_fetch_data()does:- Fetch the full data from cache:
$data = views_cache_get('views_data', TRUE); - If cache data where found, store them into the static cache:
if (!empty($data->data)) { $cache = $data->data; } - (ERROR) Check if
$cachecontains data - rebuild if empty:
if (empty($cache)) { $cache = _views_fetch_data_build(); } $fully_loaded = TRUE;Remember, we called
_views_fetch_data()before this with tables, which means the static cache ($cache) wont be empty even if the full cache isn't available! So we miss a maybe crucial cache rebuild here.
And it gets worse,$fully_loadedis set to TRUE, which means subsequent calls to_views_fetch_data()with a table won't even try to restore missing table cache entries but just mark them as missing and thus persisting the issue for every table.
- Fetch the full data from cache:
This error specifically affects redis (configured as with max-memory and LRU) as well as memcache since those caching backends will evict "random" items if the memory limit is reached.
Proposed resolution
Solution to this: Use the same code to fetch / rebuild the general cache as in the table specific part of _views_fetch_data():
// Try to load the full views cache.
if ($data = views_cache_get('views_data', TRUE)) {
$cache = $data->data;
}
else {
// No cache entry, rebuild.
$cache = _views_fetch_data_build();
}
Remaining tasks
User interface changes
API changes
| Comment | File | Size | Author |
|---|---|---|---|
| #1 | views-_views_fetch_data-prone-to-cache-inconsistency-test-only.patch | 1.58 KB | das-peter |
| #1 | views-_views_fetch_data-prone-to-cache-inconsistency.patch | 2.18 KB | das-peter |
Comments
Comment #1
das-peter commentedComment #2
das-peter commentedComment #5
dawehnerI quickly checked D8. There we have fixed the problem by having two separate static storages, so that particular problem doens't appear.
Sadly the Drupal.org testbot is kinda broken for views.
Comment #6
torgospizzaThanks for doing this, das-peter. This does look like the issue that a lot of people are seeing manifest in various ways, e.g. #2442021: Broken/missing handler after upgrade
I will test this patch. Thanks!
Comment #7
marcelovaniI get a 404 page when I browse /node/2475669
I can only see the contents if I browse /node/2475669/edit
Comment #8
marcelovanithe error is actually 403 - Access denied
Comment #9
das-peter commentedThis was escalated to Views - Critical - Access Bypass - SA-CONTRIB-2015-103 and due the security policy the issue was unpublished.
I'll see that the issue is published again.
Comment #11
rlmumfordHappy to make this a new ticket if that is the right thing to do however, I still have this problem on views 7.x-3.11.
Comment #12
joelpittet@rlmumford a client has run into this as well. In my case it's redis and views overriden via
hook_views_default_views_alter()Comment #13
joelpittetMight be more of a ctools problem in my case about not having the hook_views_api impelmented or something, but if I run into it again I'll create a follow-up and investigate.
Comment #14
fabianx commentedBack to fixed, as no one could reproduce.