There is a race condition under certain scenarios in the memcache-lock.inc file. It seems dmemcache_object() calls MemCacheDrupal->get() which calls lock_acquire(). You will get a fatal error as the lock has not yet been included.
Fatal error: Call to undefined function lock_acquire() in /home/vagrant/devel/drupal-7/sites/all/modules/contrib/memcache/memcache.inc on line 90
Call Stack:
0.0004 691960 1. {main}() /usr/share/pear/drush/drush.php:0
0.0184 4837200 2. drush_main() /usr/share/pear/drush/drush.php:16
0.0778 10776240 3. _drush_bootstrap_and_dispatch() /usr/share/pear/drush/drush.php:61
0.0974 10781576 4. drush_bootstrap_to_phase() /usr/share/pear/drush/drush.php:81
0.0974 10781576 5. drush_bootstrap_max() /usr/share/pear/drush/includes/bootstrap.inc:291
0.1449 14002840 6. drush_bootstrap() /usr/share/pear/drush/includes/bootstrap.inc:345
0.1453 14004000 7. _drush_bootstrap_drupal_full() /usr/share/pear/drush/includes/bootstrap.inc:185
0.1453 14045072 8. drupal_bootstrap() /usr/share/pear/drush/includes/bootstrap.inc:930
0.1453 14045032 9. _drupal_bootstrap_variables() /home/vagrant/devel/drupal-7/includes/bootstrap.inc:2194
0.1454 14050920 10. require_once('/home/vagrant/devel/drupal-7/sites/all/modules/contrib/memcache/memcache-lock.inc') /home/vagrant/devel/drupal-7/includes/bootstrap.inc:2413
0.1454 14051256 11. dmemcache_object() /home/vagrant/devel/drupal-7/sites/all/modules/contrib/memcache/memcache-lock.inc:16
0.1454 14051480 12. class_exists() /home/vagrant/devel/drupal-7/sites/all/modules/contrib/memcache/dmemcache.inc:292
0.1454 14051936 13. drupal_autoload_class() /home/vagrant/devel/drupal-7/sites/all/modules/contrib/memcache/dmemcache.inc:0
0.1454 14052016 14. _registry_check_code() /home/vagrant/devel/drupal-7/includes/bootstrap.inc:3026
0.1454 14052344 15. cache_get() /home/vagrant/devel/drupal-7/includes/bootstrap.inc:3053
0.1457 14058624 16. MemCacheDrupal->get() /home/vagrant/devel/drupal-7/includes/cache.inc:56
| Comment | File | Size | Author |
|---|---|---|---|
| #15 | memcache-stampede_broken-2099893-15.patch | 755 bytes | plach |
| #14 | memcache-stampede_broken-2099893-14.patch | 694 bytes | plach |
| #9 | memcache-typo-2099893-9.patch | 678 bytes | helmo |
| #7 | memcache-lock-error.patch | 2.19 KB | jeremy |
| #2 | memcache-fix-for-race-condition-in-locking-framework-2099893-2.patch | 618 bytes | JStarcher |
Comments
Comment #1
socialnicheguru commentedI am seeing this too. so using the lock through memcache is unworkable right now
Comment #2
JStarcher commentedActually good to hear that I'm not the only one.
GIve this patch a try and let us know- it's working great for me.
Comment #3
JStarcher commentedComment #4
JStarcher commentedComment #5
socialnicheguru commentedmoving the right direction.
But there is another error
PHP Fatal error: Call to undefined function lock_acquire() in modules/all/memcache/memcache.inc on line 96
The lines are
Comment #6
JStarcher commentedLooking at this again I see that really there needs to be a better way to check if memcache is working rather than calling dmecache_object() since dmemcache_object() creates a lock on misses. I also looked at simply trying to set a variable with dmemcache_set() and checking the output but that can ask for a lock as well.
Comment #7
jeremy commentedI was able to duplicate this by enabling page_cache_without_database and hitting a page that's not currently in the cache. The attached patch fixes for me, please test.
Comment #8
jeremy commentedActually, we need to load it properly through the bootstrap or our lock is going to get lost when we reinit during bootstrap. Fix committed:
http://drupalcode.org/project/memcache.git/commitdiff/1279c66
Comment #9
helmo commentedSorry to re-open this, but a typo is introduced... $this->lockInit instead of $this->lockInit()
This patch fixes it.
Comment #10
markpavlitski commentedApplies cleanly and fixes the issue.
Comment #11
jeremy commentedOuch, thanks!
Patch applied:
http://drupalcode.org/project/memcache.git/commitdiff/9582289
Comment #13
fabianx commentedThis effectively breaks all sites using stampede protection. A BIG do not upgrade or disable stampede protection is in order:
The reason is:
is always FALSE, because lockInit() does not return TRUE;
The consequence is that any expired cache item WILL ALWAYS BE RETURNED, until memcache is restarted, which is effectively a never expiring cache.
There is no cache_clear_all() or anything that will fix that condition - ever, because everything after the expired item is in else blocks and never executed.
is the proper fix. This makes it possible to keep this->lockInit() within it if () call, which is important to only load it on demand for the second scenario where it is called.
Comment #14
plachThis implements #13.
Comment #15
plachBetter PHP doc
Comment #16
fabianx commentedRTBC - works locally for me
Comment #18
plachI guess this is fixed :)
Comment #19
fabianx commentedBack to normal