Compare commits
2
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
213cf2d810 | ||
|
|
2ed2ffc139 |
@@ -1,3 +1,81 @@
|
||||
# php_semaphores
|
||||
# posix_semaphores - POSIX semaphores extension for PHP
|
||||
|
||||
POSIX semaphores extension for PHP
|
||||
## Introduction
|
||||
|
||||
This a thin wrapper around [POSIX semaphores API](http://man7.org/linux/man-pages/man7/sem_overview.7.html).
|
||||
There is built-in PHP extension for [semaphores and other IPC](https://www.php.net/manual/en/book.sem.php),
|
||||
but it supports only System V semaphores, when POSIX version has much more convenient API.
|
||||
|
||||
Also System V semaphore support in PHP does not match exactly with C API (in fact it constructs three semaphores
|
||||
in set under the hood and uses them for initialization and other bookkeeping tasks). That's very convenient
|
||||
when one uses semaphores solely from PHP code, but prevents some mixed use cases when one wants to sync PHP code
|
||||
and other code with semaphores.
|
||||
|
||||
For example it's not possible to create locked semaphore in C++ application, wait for it in PHP (with locking
|
||||
of course) and then unlock in C++ application (this case could be used for shared memory IPC syncronization, for instance).
|
||||
|
||||
So the goal here is to make C API wrapper as thin as possible to allow simultaneous usage of semaphores in
|
||||
applications written in PHP or other programming languages.
|
||||
|
||||
## Installation
|
||||
|
||||
Make sure you have `php-devel` package installed in your system. You need to be able to build PHP extensions.
|
||||
|
||||
After that run commands:
|
||||
```
|
||||
phpize
|
||||
./configure --enable-posix_semaphores
|
||||
make
|
||||
```
|
||||
|
||||
If everything goes well, you will have file `./modules/posix_semaphores.so`. The last step is to include this file
|
||||
into your `php.ini`. Add line `extension=/<PATH>/posix_semaphores.so` (replace `<PATH>` with actual path to this
|
||||
extension) and you're done. Don't forget to restart php-fpm or apache if you're using PHP from there.
|
||||
|
||||
## Reference
|
||||
|
||||
Extension consists of several functions which are clearly mapped to POSIX semaphores API.
|
||||
|
||||
### posix_sem_open($name, $flags, $mode = 0666, $value = 0)
|
||||
|
||||
This is equivalent of [sem_open](http://man7.org/linux/man-pages/man3/sem_open.3.html).
|
||||
|
||||
Parameters:
|
||||
* $name - name of semaphore to open,
|
||||
* $flags - opening flags (such as O_CREAT or O_EXCL),
|
||||
* $mode - opening mode (default value is 0666),
|
||||
* $value - initial value for semaphore (default is 0).
|
||||
|
||||
Function returns semaphore resource on success or `null` on failure.
|
||||
|
||||
### posix_sem_close($semaphore)
|
||||
|
||||
Function closes semaphore resource (in fact it's just a proxy to [sem_close](http://man7.org/linux/man-pages/man3/sem_close.3.html)).
|
||||
|
||||
Parameters:
|
||||
* $semaphore - semaphore resource acquired via `posix_sem_open`.
|
||||
|
||||
Returns `true` on success, `false` otherwise.
|
||||
|
||||
### posix_sem_unlink($name)
|
||||
|
||||
Unlinks named semaphore from system. The semaphore name is removed immediately. The semaphore itself is removed when
|
||||
all processed having the semaphore opened, close it.
|
||||
|
||||
Parameters:
|
||||
* $name - name of semaphore to remove.
|
||||
|
||||
Returns `true` on success, `false` otherwise.
|
||||
|
||||
### posix_sem_post($semaphore)
|
||||
|
||||
### posix_sem_wait($semaphore)
|
||||
|
||||
### posix_sem_getvalue($semaphore)
|
||||
|
||||
|
||||
## Notes for PHP users
|
||||
|
||||
All semaphore resources are closed automatically when PHP exits. But underlying semaphores are not unlinked by default. You
|
||||
should use `register_shutdown_function` to unlink all semaphores which you don't need after program exit.
|
||||
Alternative way for that is to manage semaphore creation and deletion outside of PHP.
|
||||
|
||||
+81
-2
@@ -17,6 +17,9 @@ static zend_function_entry posix_semaphores_functions[] = {
|
||||
PHP_FE(posix_sem_getvalue, NULL)
|
||||
PHP_FE(posix_sem_post, NULL)
|
||||
PHP_FE(posix_sem_wait, NULL)
|
||||
PHP_FE(posix_sem_trywait, NULL)
|
||||
PHP_FE(posix_sem_timedwait, NULL)
|
||||
PHP_FE(posix_sem_error, NULL)
|
||||
{NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
@@ -58,6 +61,7 @@ static void php_posix_semaphore_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
||||
sem_close(s->sem);
|
||||
s->sem = NULL;
|
||||
}
|
||||
efree(s);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -66,9 +70,13 @@ static void php_posix_semaphore_dtor(zend_rsrc_list_entry *rsrc TSRMLS_DC)
|
||||
// list entry identifier
|
||||
int le_posix_semaphore;
|
||||
|
||||
// error which occured during last function call
|
||||
int last_errno;
|
||||
|
||||
PHP_MINIT_FUNCTION(posix_semaphores)
|
||||
{
|
||||
le_posix_semaphore = zend_register_list_destructors_ex(php_posix_semaphore_dtor, NULL, PHP_POSIX_SEMAPHORES_RES_NAME, module_number);
|
||||
last_errno = 0;
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -95,7 +103,7 @@ PHP_FUNCTION(posix_sem_open)
|
||||
sem_t* sem = sem_open(name, flags, mode, value);
|
||||
if (sem == SEM_FAILED)
|
||||
{
|
||||
printf("sem_open failed, errno = %d flags = %d O_CREAT = %d", errno, flags, O_CREAT);
|
||||
last_errno = errno;
|
||||
RETURN_NULL();
|
||||
}
|
||||
php_posix_semaphore *semaphore = emalloc(sizeof(php_posix_semaphore));
|
||||
@@ -117,6 +125,7 @@ PHP_FUNCTION(posix_sem_close)
|
||||
{
|
||||
if (sem_close(semaphore->sem) == -1)
|
||||
{
|
||||
last_errno = errno;
|
||||
RETURN_FALSE;
|
||||
}
|
||||
semaphore->sem = NULL;
|
||||
@@ -135,7 +144,8 @@ PHP_FUNCTION(posix_sem_unlink)
|
||||
}
|
||||
if (sem_unlink(name) == -1)
|
||||
{
|
||||
RETURN_FALSE;
|
||||
last_errno = errno;
|
||||
RETURN_FALSE;
|
||||
}
|
||||
RETURN_TRUE;
|
||||
}
|
||||
@@ -155,6 +165,7 @@ PHP_FUNCTION(posix_sem_getvalue)
|
||||
int value;
|
||||
if (sem_getvalue(semaphore->sem, &value) == -1)
|
||||
{
|
||||
last_errno = errno;
|
||||
RETURN_NULL();
|
||||
}
|
||||
else
|
||||
@@ -182,6 +193,7 @@ PHP_FUNCTION(posix_sem_post)
|
||||
{
|
||||
if (sem_post(semaphore->sem) == -1)
|
||||
{
|
||||
last_errno = errno;
|
||||
RETURN_FALSE;
|
||||
}
|
||||
else
|
||||
@@ -209,6 +221,7 @@ PHP_FUNCTION(posix_sem_wait)
|
||||
{
|
||||
if (sem_wait(semaphore->sem) == -1)
|
||||
{
|
||||
last_errno = errno;
|
||||
RETURN_FALSE;
|
||||
}
|
||||
else
|
||||
@@ -222,3 +235,69 @@ PHP_FUNCTION(posix_sem_wait)
|
||||
}
|
||||
}
|
||||
|
||||
PHP_FUNCTION(posix_sem_trywait)
|
||||
{
|
||||
php_posix_semaphore *semaphore;
|
||||
zval *zsemaphore;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "r", &zsemaphore) == FAILURE)
|
||||
{
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(semaphore, php_posix_semaphore*, &zsemaphore, -1, PHP_POSIX_SEMAPHORES_RES_NAME, le_posix_semaphore);
|
||||
if (semaphore->sem)
|
||||
{
|
||||
if (sem_trywait(semaphore->sem) == -1)
|
||||
{
|
||||
last_errno = errno;
|
||||
RETURN_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
PHP_FUNCTION(posix_sem_timedwait)
|
||||
{
|
||||
php_posix_semaphore *semaphore;
|
||||
zval *zsemaphore;
|
||||
long timeout_sec;
|
||||
long timeout_nsec = 0;
|
||||
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "rl|l", &zsemaphore, &timeout_sec, &timeout_nsec) == FAILURE)
|
||||
{
|
||||
RETURN_FALSE;
|
||||
}
|
||||
|
||||
ZEND_FETCH_RESOURCE(semaphore, php_posix_semaphore*, &zsemaphore, -1, PHP_POSIX_SEMAPHORES_RES_NAME, le_posix_semaphore);
|
||||
if (semaphore->sem)
|
||||
{
|
||||
struct timespec tm;
|
||||
tm.tv_sec = (int)timeout_sec;
|
||||
tm.tv_nsec = (int)timeout_nsec;
|
||||
if (sem_timedwait(semaphore->sem, &tm) == -1)
|
||||
{
|
||||
last_errno = errno;
|
||||
RETURN_FALSE;
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_TRUE;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
RETURN_FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
PHP_FUNCTION(posix_sem_error)
|
||||
{
|
||||
RETURN_LONG(last_errno);
|
||||
}
|
||||
|
||||
@@ -13,6 +13,9 @@ PHP_FUNCTION(posix_sem_unlink);
|
||||
PHP_FUNCTION(posix_sem_getvalue);
|
||||
PHP_FUNCTION(posix_sem_post);
|
||||
PHP_FUNCTION(posix_sem_wait);
|
||||
PHP_FUNCTION(posix_sem_trywait);
|
||||
PHP_FUNCTION(posix_sem_timedwait);
|
||||
PHP_FUNCTION(posix_sem_error);
|
||||
|
||||
extern zend_module_entry posix_semaphores_module_entry;
|
||||
#define phpext_posix_semaphores_ptr &posix_semaphores_module_entry;
|
||||
|
||||
Reference in New Issue
Block a user