php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #58172 apc_add() deletes variables on second call
Submitted: 2008-04-21 17:47 UTC Modified: 2008-06-26 08:18 UTC
From: dmitrij at stepanov dot lv Assigned:
Status: Closed Package: APC (PECL)
PHP Version: 5.2.5 OS: Windows XP
Private report: No CVE-ID: None
View Add Comment Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
You can add a comment by following this link or if you reported this bug, you can edit this bug over here.
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: dmitrij at stepanov dot lv
New email:
PHP Version: OS:

 

 [2008-04-21 17:47 UTC] dmitrij at stepanov dot lv
Description:
------------
A couple of months ago i had to write a server-local RAM cache with PHP to store and cache information within one web server (one apache process). I did a lot of benchmarks and tests on different kind of caches available for php and APC seemed to fit the best for my needs. One of the functionalities i had to have is the cache locking by concurrent requests, so that only one request processing thread at a time could access cache. This can be done (according to documentation at http://www.php.net/manual/en/function.apc-add.php) using apc_add() function to create entries exclusively.

See the following code:

function TryLock() {
  return apc_add( '_lock', 1, 0);
}
funciton Unlock() {
 apc_delete( '_lock');
}
while( !TryLock())
 usleep( 10);
... // do something with cache
Unlock();

Imagine two threads executing this code. The thread, which first gets apc_add() returned true, acquires lock and gains control over the cache, until that thread calls Unlock() (deletes the '_lock' key).
The problem is that on my configuration - WINDOWS XP, Apache 2.2.4.0, PHP 5.2.5.5, APC 5.2.5.5, this mechanism does not work, because the second call to apc_add with key '_lock' forces this entry to be deleted from cache. The bug is: the second call of two calls to apc_add() with equal key parameter force the entry to be deleted from cache.. I have tested this code on Linux, and it works as expected.

Reproduce code:
---------------
var_dump( apc_add( '_lock', 1, 0));
$info =apc_cache_info( 'user'); var_dump( $info['cache_list']);
var_dump( apc_add( '_lock', 1, 0));
$info =apc_cache_info( 'user'); var_dump( $info['cache_list']);
var_dump( apc_add( '_lock', 1, 0));
$info =apc_cache_info( 'user'); var_dump( $info['cache_list']);
var_dump( apc_add( '_lock', 1, 0));
$info =apc_cache_info( 'user'); var_dump( $info['cache_list']);

Expected result:
----------------
bool(true)
array(1) {
  [0]=>
  array(10) {
    ["info"]=>
    string(5) "_lock"
    ["ttl"]=>
    int(0)
    ["type"]=>
    string(4) "user"

    ["num_hits"]=>
    int(0)
    ["mtime"]=>
    int(1208725222)
    ["creation_time"]=>
    int(1208725222)
    ["deletion_time"]=>
    int(0)

    ["access_time"]=>
    int(1208725222)
    ["ref_count"]=>
    int(0)
    ["mem_size"]=>
    int(96)
  }
}
bool(false)
array(1) {
  [0]=>
  array(10) {

    ["info"]=>
    string(5) "_lock"
    ["ttl"]=>
    int(0)
    ["type"]=>
    string(4) "user"
    ["num_hits"]=>
    int(0)

    ["mtime"]=>
    int(1208725222)
    ["creation_time"]=>
    int(1208725222)
    ["deletion_time"]=>
    int(0)
    ["access_time"]=>
    int(1208725222)

    ["ref_count"]=>
    int(0)
    ["mem_size"]=>
    int(96)
  }
}
bool(false)
array(1) {
  [0]=>
  array(10) {
    ["info"]=>
    string(5) "_lock"

    ["ttl"]=>
    int(0)
    ["type"]=>
    string(4) "user"
    ["num_hits"]=>
    int(0)
    ["mtime"]=>
    int(1208725222)
    ["creation_time"]=>

    int(1208725222)
    ["deletion_time"]=>
    int(0)
    ["access_time"]=>
    int(1208725222)
    ["ref_count"]=>
    int(0)
    ["mem_size"]=>

    int(96)
  }
}
bool(false)
array(1) {
  [0]=>
  array(10) {
    ["info"]=>
    string(5) "_lock"
    ["ttl"]=>
    int(0)
    ["type"]=>

    string(4) "user"
    ["num_hits"]=>
    int(0)
    ["mtime"]=>
    int(1208725222)
    ["creation_time"]=>
    int(1208725222)
    ["deletion_time"]=>

    int(0)
    ["access_time"]=>
    int(1208725222)
    ["ref_count"]=>
    int(0)
    ["mem_size"]=>
    int(96)
  }
}

Actual result:
--------------
bool(true)
array(1) {
  [0]=>
  array(10) {
    ["info"]=>
    string(5) "_lock"
    ["ttl"]=>
    int(0)
    ["type"]=>

    string(4) "user"
    ["num_hits"]=>
    int(0)
    ["mtime"]=>
    int(1208725222)
    ["creation_time"]=>
    int(1208725222)
    ["deletion_time"]=>

    int(0)
    ["access_time"]=>
    int(1208725222)
    ["ref_count"]=>
    int(0)
    ["mem_size"]=>
    int(96)
  }
}
bool(false)
array(0) {
}

bool(true)
array(1) {
  [0]=>
  array(10) {
    ["info"]=>
    string(5) "_lock"
    ["ttl"]=>
    int(0)
    ["type"]=>
    string(4) "user"

    ["num_hits"]=>
    int(0)
    ["mtime"]=>
    int(1208725222)
    ["creation_time"]=>
    int(1208725222)
    ["deletion_time"]=>
    int(0)

    ["access_time"]=>
    int(1208725222)
    ["ref_count"]=>
    int(0)
    ["mem_size"]=>
    int(96)
  }
}
bool(false)
array(0) {
}

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2008-04-23 12:01 UTC] daniz at rocketmail dot com
Hopefully this bug is something similar to my problem at http://pecl.php.net/bugs/bug.php?id=13558 regarding the lock of add/delete. There is surely something wrong with the code, I just had a problem reproducing it in a closed environment.
 [2008-04-23 14:07 UTC] gopalv82 at yahoo dot com
Same as http://pecl.php.net/bugs/bug.php?id=12499 ?

We reverted that patch for 3.0.18 because it was suspected of breaking code, but the CVS HEAD (i.e the php5+ only branch) retains the expunge fixes.
 [2008-06-26 08:18 UTC] gopalv82 at yahoo dot com
Fixed in apc-3.1.x-dev branch.

Please check out CVS HEAD to test it.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 25 14:01:31 2024 UTC