/**
* This is a wrapper for APCU's shared memory functions
*
+ * Use PHP serialization to avoid bugs and easily create CAS tokens.
+ * APCu has a memory corruption bug when the serializer is set to 'default'.
+ * See T120267, and upstream bug reports:
+ * - https://github.com/krakjoe/apcu/issues/38
+ * - https://github.com/krakjoe/apcu/issues/35
+ * - https://github.com/krakjoe/apcu/issues/111
+ *
* @ingroup Cache
*/
-class APCUBagOStuff extends APCBagOStuff {
+class APCUBagOStuff extends BagOStuff {
+ /** @var bool Whether to trust the APC implementation to serialization */
+ private $nativeSerialize;
+
/**
- * Available parameters are:
- * - nativeSerialize: If true, pass objects to apcu_store(), and trust it
- * to serialize them correctly. If false, serialize
- * all values in PHP.
- *
- * @param array $params
+ * @var string String to append to each APC key. This may be changed
+ * whenever the handling of values is changed, to prevent existing code
+ * from encountering older values which it cannot handle.
*/
+ const KEY_SUFFIX = ':4';
+
public function __construct( array $params = [] ) {
parent::__construct( $params );
+ // The extension serialize is still buggy, unlike "php" and "igbinary"
+ $this->nativeSerialize = ( ini_get( 'apc.serializer' ) !== 'default' );
}
protected function doGet( $key, $flags = 0, &$casToken = null ) {
}
public function set( $key, $value, $exptime = 0, $flags = 0 ) {
- apcu_store(
+ return apcu_store(
$key . self::KEY_SUFFIX,
$this->serialize( $value ),
$exptime
);
-
- return true;
}
public function add( $key, $value, $exptime = 0, $flags = 0 ) {
}
public function incr( $key, $value = 1 ) {
- /**
- * @todo When we only support php 7 or higher remove this hack
- *
- * https://github.com/krakjoe/apcu/issues/166
- */
+ // https://github.com/krakjoe/apcu/issues/166
if ( apcu_exists( $key . self::KEY_SUFFIX ) ) {
return apcu_inc( $key . self::KEY_SUFFIX, $value );
} else {
}
public function decr( $key, $value = 1 ) {
- /**
- * @todo When we only support php 7 or higher remove this hack
- *
- * https://github.com/krakjoe/apcu/issues/166
- */
+ // https://github.com/krakjoe/apcu/issues/166
if ( apcu_exists( $key . self::KEY_SUFFIX ) ) {
return apcu_dec( $key . self::KEY_SUFFIX, $value );
} else {
return false;
}
}
+
+ protected function serialize( $value ) {
+ if ( $this->nativeSerialize ) {
+ return $value;
+ }
+
+ return $this->isInteger( $value ) ? (int)$value : serialize( $value );
+ }
+
+ protected function unserialize( $value ) {
+ if ( $this->nativeSerialize ) {
+ return $value;
+ }
+
+ return $this->isInteger( $value ) ? (int)$value : unserialize( $value );
+ }
}