Reply to thread

I'm getting similar errors that indicate that sometimes false is returned from the cache (instead of null).


XenForo uses the Doctrine RedisCache to store serialized PHP values in Redis. I think there is a race condition in this library: https://github.com/doctrine/cache/blob/master/lib/Doctrine/Common/Cache/RedisCache.php#L60


RedisCache calls "mget" to fetch multiple values. If one of these values is returned as false then it double-checks whether the value really doesn't exist by calling the "exists" method on the key. Now, if the value has just been (re-)created between the "mget" and the "exists" call then it thinks that false is the value of the specified key (although it isn't).


This is a conceptional issue of letting PhpRedis serialize the data (instead of doing that in the RedisCache library). With serialization enabled, PhpRedis returns false for a) keys that don't exist and b) for keys that exist and have the value false. To distinguish between these two cases, RedisCache uses the "exists" call which unfortunately introduces the described race condition.


Is false a legitimate cache value in XenForo? If not then the "exists" call could just be removed. The other alternative would be to modify RedisCache such that it does the serialization on its own.


[CODE]

TypeError: Argument 1 passed to XF\SimpleCache::__construct() must be of the type array, boolean given, called in src/XF/App.php on line 549 src/XF/SimpleCache.php:12


Stack trace

#0 src/XF/App.php(549): XF\SimpleCache->__construct(false)

#1 src/XF/Container.php(28): XF\App->XF\{closure}(Object(XF\Container))

#2 src/XF/App.php(2150): XF\Container->offsetGet('simpleCache')

#3 src/XF/App.php(1678): XF\App->simpleCache()

#4 src/XF/App.php(1601): XF\App->getGlobalTemplateData(Object(XF\Mvc\Reply\View))

#5 src/XF/Pub/App.php(350): XF\App->preRender(Object(XF\Mvc\Reply\View), 'json')

#6 src/XF/Mvc/Dispatcher.php(280): XF\Pub\App->preRender(Object(XF\Mvc\Reply\View), 'json')

#7 src/XF/Mvc/Dispatcher.php(44): XF\Mvc\Dispatcher->render(Object(XF\Mvc\Reply\View), 'json')

#8 src/XF/App.php(1945): XF\Mvc\Dispatcher->run()

#9 src/XF.php(328): XF\App->run()

#10 index.php(13): XF::runApp('XF\\Pub\\App')

#11 {main}

[/CODE]


[CODE]

Uncaught TypeError: Argument 1 passed to XF\App::XF\{closure}() must be of the type array, boolean given, called in src/XF/App.php on line 1460 and defined in src/XF/App.php:555


Stack trace:

#0 src/XF/App.php(1460): XF\App->XF\{closure}(false, Object(XF\Container), 'options')

#1 src/XF/Container.php(28): XF\App->XF\{closure}(Object(XF\Container))

#2 src/XF/App.php(2158): XF\Container->offsetGet('options')

#3 src/XF.php(463): XF\App->options()

#4 src/XF/Entity/User.php(1614): XF::options()

#5 src/XF/Mvc/Entity/Manager.php(70): XF\Entity\User::getStructure(Object(XF\Mvc\Entity\Structure))

#6 src/XF/Repository/User.php(60): XF\Mvc\Entity\Manager->getEntityStructure('XF:User')

#7 src/XF/Repository/User.php(31): XF\Repository\User->getGuestUser()

#8 src/XF.php(367): XF\Repository\User->getVisitor(0)

#9 src/XF/Error.php(132): XF::visitor()

#10 src/XF/App.php(1956): XF\Error->logException(Object(ErrorException), false, '')

#11 src/XF.php(184): XF\App->logException(Object(ErrorException))

#12 [internal function]: XF::handleFatalError()

#13 {main}

  thrown in src/XF/App.php on line 555

[/CODE]


Back
Top Bottom