Skip to content

cache.inc: BoincMemcache::get() rebuilds the Memcached connection and re-adds servers on every call #7318

Description

@FraSanga

Describe the bug

html/inc/cache.inc, BoincMemcache::get():

class BoincMemcache {
    static $instance;

    static function get() {
        self::$instance = new Memcached;
        if (defined('MEMCACHE_PREFIX')) {
            self::$instance->setOption(Memcached::OPT_PREFIX_KEY, MEMCACHE_PREFIX);
        }
        $server_arr = array();
        $servers = explode('|', MEMCACHE_SERVERS);
        foreach($servers as &$server) {
            list($ip, $port, $weight) = explode(':', $server);
            if (!$port) { $port = 11211; }
            $server_arr[] = array($ip, $port, $weight);
        }
        self::$instance->addServers($server_arr);
        return self::$instance;
    }
}

self::$instance is written but never read as a guard, so every call does new Memcached + setOption() + addServers() again. On a memcached-backed project that's once per get_cached_data() / set_cached_data(), i.e. potentially several times per page load.

Two problems with re-running this:

  • new Memcached with no persistent_id opens a fresh connection pool per object instead of reusing one.
  • Memcached::addServers() on an instance that already has servers appends duplicate entries (per the PHP manual's note on addServer()/addServers()), skewing the weighting / hashing.

Suggested fix

Return the memoized instance:

static function get() {
    if (self::$instance) return self::$instance;
    self::$instance = new Memcached;
    ...
}

MEMCACHE_PREFIX / MEMCACHE_SERVERS are constants, so nothing needs re-reading within a request. (A persistent_id connection — new Memcached('boinc') — would be the fuller fix, but that's a separate change.)

Found while reviewing #6310; independent of that.


Reported with AI assistance (Claude Sonnet 5); verified against master @ b4b1bad96f.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Type

Projects

  • Status
    Backlog

Relationships

None yet

Development

No branches or pull requests

Issue actions