I have implemented an access control for insertions into a database table that is used for a reservation service. It works fine for some time, then the sem_get()
function fails despite the fact that I call sem_release()
after every sem_get()
.
case 'room':
$key = "room";
$semaphore = sem_get($key, 1, 0666, 1);
if ($semaphore) {
sem_acquire($semaphore);
//do some stuff
if ($already_reserved_rooms < $max_rooms) {
$return="ok";
sem_release($semaphore);
return $return;
}
sem_release($semaphore);
}
else {
//send me mail that semaphore failed
}
return 'no rooms';
break;
Should I call sem_remove()
as well?
I followed steps on this site.
The sem_get () function is provided by the Semaphore, Shared Memory and IPC component. This extension is not available on Windows platforms. Thanks for contributing an answer to Stack Overflow!
When using sem_get() to access a semaphore created outside PHP, note that the semaphore must have been created as a set of 3 semaphores (for example, by specifying 3 as the nsems parameter when calling the C semget() function), otherwise PHP will be unable to access the semaphore.
A second call to sem_get () for the same key will return a different semaphore identifier, but both identifiers access the same underlying semaphore. If key is 0, a new private semaphore is created for each call to sem_get () .
the sem_get
function returns false in your case, because you give a string instead of integer.
Replace
$semaphore = sem_get($key, 1, 0666, 1);
by
$semaphore = sem_get(crc32($key), 1, 0666, 1);
It will work
Removing Semaphores
Yes, you should call sem_remove()
when you are done with the semaphore set. Otherwise, the semaphore set will persist in the system until you remove it. However, the fact that the semaphore set persists causes no problem while the number of semaphores is less than the SEMMNS
limit:
SEMMNS
System-wide limit on the number of semaphores: policy dependent (on Linux, this limit can be read and modified via the second field of/proc/sys/kernel/sem
).
sem_remove()
immediately removes the semaphore set awakening all processes blocked using this semaphore.
By the way, you can use the ipcrm
command to remove semaphores from command line, and the ipcs
command to show information on IPC facilities (including semaphores).
Releasing Semaphores
You are not required to call sem_release()
while the auto-release flag (sem_get
's 4th parameter) is on. But it is a good idea to release semaphores as long as you don't need the acquired "lock".
sem_release()
only increments the value of internal semaphore. Think of it as an unlocking operation, the opposite of sem_acquire()
.
sem_get()
Failures
The sem_get()
function returns FALSE
in the following cases
E_ERROR
);E_WARNING
);E_WARNING
);E_WARNING
)In each of the cases sem_get
logs an error, or a warning. So you have to check the logs in order to find out the root of the problem.
Since your code works for some time, it is not parameter parsing issue, and not the permissions. Memory allocation issues are rare. So it is very likely that you are running out of the semaphore number limits. Check out the man page for semget
for reference. The man page describes how to read and modify the limits via /proc/sys/kernel/sem
.
Refer to this answer for more information regarding the sysvsem
extension internals.
The $key argument for sem_get() is integer, while you are passing it as string. Please consider getting the integer key by the ftok() call.
So please consider replacing
$key = "room";
to the following code:
$project = "r"; // Project identifier. This must be a one character string.
$key = ftok(__FILE__, $project);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With