Self-diagnosed and fixed W3 Total Cache bug in faulty object caching
-
Evening folks and Frederick,
As some of you may know, there has been an issue with object caching not returning values and various side effects like WP-Cron not running lingering in W3TC code for, I believe, years (I may be wrong, but some of the posts I found go back that far).
I spent several days tracking down the bug inside Memcached caching for object caching not working, and finally with the help of a live remote debugger, I’ve figured out where the bug is.
The bug and diagnosis
Relevant files in W3TC (0.9.4 as of today):
- lib/W3/Cache/Base.php
- lib/W3/Cache/Memcached.php
- lib/W3/Cache/ObjectCache.php
To recap, a large arbitrary portion of the cached objects aren’t returned correctly. As I found out, they are, in fact, in memcached, but there is a bug with the so called “key_version” which W3 uses to split the values into different buckets that has erroneous logic that ends up setting value V into bucket with key_version A but when getting it, it ends up using a bucket with key_version B.
This in turn means that values that are continuously getting set aren’t retrieved and are then set again, over and over, many times a second in some cases. Outside of the fact that caching plain doesn’t work, that also means evictions are much more frequent and end up in expiring values that do happen to work much-much faster.
In actuality, it all comes down to the default values used for the variable $group in various getters and setters in lib/W3/Cache/Memcached.php (by default $group = 0) and its parent lib/W3/Cache/Base.php (by default $group = ”).
Both lib/W3/Cache/Memcached.php and lib/W3/Cache/Base.php contain set() but only lib/W3/Cache/Memcached.php contains get(). Because of this, the $group getting passed to the function that calculates the right bucket and key_version is “0” for set() and ” for get(). At this point the get() function throws away the correctly returned from memcached value and returns null because key_version doesn’t match.
The fix
The quick and dirty fix is to add the missing get() function into lib/W3/Cache/Memcached.php, like so:
function get($key, $group = '0') { return parent::get($key, $group); }
This will realign the $group defaults to be the same for get() and set(). I’ve verified that this fix works.
This quick fix above, however, isn’t 100% complete, as I believe the grouping functionality remains broken altogether since it basically forces only two groups with keys ‘0’ and ” (empty), but at least it fixes this major bug because the data is set and gotten from the same groups. I’m going to post the other part of the answer in a follow-up reply to split things up a bit.
- The topic ‘Self-diagnosed and fixed W3 Total Cache bug in faulty object caching’ is closed to new replies.