24

I've got the following code and the semaphore wouldn't lock it as expected.

(I'm aware of apc_inc. This is not what I'm looking for.)

$semkey = sem_get(123);
sem_acquire($semkey);

$count = apc_fetch('count111');
if(!$count) $count = 0;
$count++;
apc_store('count111', $count);

sem_release($semkey);

followed by

ab -n 4000 -c 200 http://localhost/test.php

0 requests failed.

but after that an apc_fetch('count111') shows only ~ 1200 hits

nginx on ubuntu 12.04 (64bit), php 5.3.16~dotdeb, php-fpm

  • update 1: works perfectly on Linux mint, 5.4.6~dotdeb, built in web server. I'm going to try the same machine with the same version with nginx.
Alex
  • 11,479
  • 6
  • 28
  • 50
  • 2
    Just to clarify: I've tried to put an `apc_inc` call inside the locked block and it got executed all the 4000 times. – Alex Sep 13 '12 at 21:00
  • As far as i understand PHP semaphore is locking shared memory and resources, not code block. I believe it will work with the PHP shared memory functions – Bnaya Sep 13 '12 at 21:55
  • 1
    I assumed sem_get initializes all the required resources and PHP's source code pretty much confirms that. They've got a direct call to posix's semget, which takes on from there. Besides, semaphores are ment to sync processes that **do not** share any memory. – Alex Sep 14 '12 at 07:53
  • 2
    Your code doesn't check the return value of sem_acquire() (it's pobably failing) – symcbean Sep 14 '12 at 08:52
  • Perhaps you are right, but according to source code ( http://lxr.php.net/xref/PHP_5_4/ext/sysvsem/sysvsem.c#298 ) all the cases where the acquire could fail are followed by an e_warning thrown, which aren't presented. That leads me to think sem_acquire ain't failing, but I'll check this out too. – Alex Sep 14 '12 at 09:05
  • 1
    I think this is apc being buggy and has nothing to with the semaphore, check the apc versions in both tests, try updating. – fd8s0 Sep 18 '12 at 22:04
  • Check out this thread http://stackoverflow.com/questions/325806/best-way-to-obtain-a-lock-in-php contains various locking solutions which may help you. – Gavin Oct 08 '12 at 18:21
  • I believe that was an apc issue. I had completed all the 4000 requests completely with latest dotdeb packages and the php's built-in server on multiple machines. – Alex Oct 16 '12 at 15:33
  • I'm thinking maybe in configuration of APC: http://php.net/manual/en/apc.configuration.php Look apc.num_files_hint "1000" PHP_INI_SYSTEM and increase apc.num_files_hint, or/and disable apc.slam_defense – Marin Sagovac Oct 19 '12 at 21:30
  • It looks to me like you would need to tell the sem_get not to release on end of request: $semkey = sem_get(123, 1, 0666, 0); – gview Oct 27 '12 at 00:01
  • @Alex: Did this now resolve for you or do you still have the issue? Is the problem with Nginx only but internal webserver works? – hakre Oct 28 '12 at 12:46
  • I guess the problem was with old APC version. This doesn't reproduce neither with nginx nor with cli web server. – Alex Oct 28 '12 at 13:45
  • @Alex Why not answer your own question then? Which is totally allowed on SO. Or close this. – Anthony Hatzopoulos Oct 29 '12 at 14:03

1 Answers1

1

The problem was, apparently, with the APC itself, not with the semaphore.
Updating to PHP 5.4.8-1~dotdeb.0 has solved the problem for both nginx and built-in server test runs.

Alex
  • 11,479
  • 6
  • 28
  • 50