Edit report at https://bugs.php.net/bug.php?id=61608&edit=1
ID: 61608
Comment by: zhanglijiu at gmail dot com
Reported by: stephane dot anthoine at gmail dot com
Summary: sem_get problem
Status: Open
Type: Bug
Package: Semaphore related
Operating System: linux 2.6.32
PHP Version: 5.4.0
Block user comment: N
Private report: N
New Comment:
what OS do you use? there is the sem_get system function:
PHP_FUNCTION(sem_get)
{
long key, max_acquire = 1, perm = 0666, auto_release = 1;
int semid;
struct sembuf sop[3];
int count;
sysvsem_sem *sem_ptr;
if (FAILURE == zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC,
"l|lll",
&key, &max_acquire, &perm, &auto_release)) {
RETURN_FALSE;
}
/* Get/create the semaphore. Note that we rely on the semaphores
* being zeroed when they are created. Despite the fact that
* the(?) Linux semget() man page says they are not initialized,
* the kernel versions 2.0.x and 2.1.z do in fact zero them.
*/
semid = semget(key, 3, perm|IPC_CREAT);
if (semid == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for key
0x%lx: %s", key, strerror(errno));
RETURN_FALSE;
}
/* Find out how many processes are using this semaphore. Note
* that on Linux (at least) there is a race condition here because
* semaphore undo on process exit is not atomic, so we could
* acquire SYSVSEM_SETVAL before a crashed process has decremented
* SYSVSEM_USAGE in which case count will be greater than it
* should be and we won't set max_acquire. Fortunately this
* doesn't actually matter in practice.
*/
/* Wait for sem 1 to be zero . . . */
sop[0].sem_num = SYSVSEM_SETVAL;
sop[0].sem_op = 0;
sop[0].sem_flg = 0;
/* . . . and increment it so it becomes non-zero . . . */
sop[1].sem_num = SYSVSEM_SETVAL;
sop[1].sem_op = 1;
sop[1].sem_flg = SEM_UNDO;
/* . . . and increment the usage count. */
sop[2].sem_num = SYSVSEM_USAGE;
sop[2].sem_op = 1;
sop[2].sem_flg = SEM_UNDO;
while (semop(semid, sop, 3) == -1) {
if (errno != EINTR) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed
acquiring SYSVSEM_SETVAL for key 0x%lx: %s", key, strerror(errno));
break;
}
}
/* Get the usage count. */
count = semctl(semid, SYSVSEM_USAGE, GETVAL, NULL);
if (count == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for key
0x%lx: %s", key, strerror(errno));
}
/* If we are the only user, then take this opportunity to set the max.
*/
if (count == 1) {
#if HAVE_SEMUN
/* This is correct for Linux which has union semun. */
union semun semarg;
semarg.val = max_acquire;
if (semctl(semid, SYSVSEM_SEM, SETVAL, semarg) == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for
key 0x%lx: %s", key, strerror(errno));
}
#elif defined(SETVAL_WANTS_PTR)
/* This is correct for Solaris 2.6 which does not have union
semun. */
if (semctl(semid, SYSVSEM_SEM, SETVAL, &max_acquire) == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for
key 0x%lx: %s", key, strerror(errno));
}
#else
/* This works for i.e. AIX */
if (semctl(semid, SYSVSEM_SEM, SETVAL, max_acquire) == -1) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed for
key 0x%lx: %s", key, strerror(errno));
}
#endif
}
/* Set semaphore 1 back to zero. */
sop[0].sem_num = SYSVSEM_SETVAL;
sop[0].sem_op = -1;
sop[0].sem_flg = SEM_UNDO;
while (semop(semid, sop, 1) == -1) {
if (errno != EINTR) {
php_error_docref(NULL TSRMLS_CC, E_WARNING, "failed
releasing SYSVSEM_SETVAL for key 0x%lx: %s", key, strerror(errno));
break;
}
}
sem_ptr = (sysvsem_sem *) emalloc(sizeof(sysvsem_sem));
sem_ptr->key = key;
sem_ptr->semid = semid;
sem_ptr->count = 0;
sem_ptr->auto_release = auto_release;
sem_ptr->id = ZEND_REGISTER_RESOURCE(return_value, sem_ptr,
php_sysvsem_module.le_sem);
}
Previous Comments:
------------------------------------------------------------------------
[2012-04-03 14:39:15] stephane dot anthoine at gmail dot com
Description:
------------
---
>From manual page:
>http://www.php.net/function.sem-get#refsect1-function.sem-get-
description
---
The sem_get function don't work if the semaphore already exist : by example
created by an other application (made in C code).
--> No sem_id returned.
If the php code is executed before this external application, the creation and
sharing runs correctly....
sem_get seems able to make a new semaphore.... but not take back the Id of an
existing semaphore.
Test script:
---------------
// On demande lâaccès
$sem_id = sem_get(0x4d2, 1, 0666, 1); <--- Return nothing
// l'accès au block mémoire est autorisé
if(sem_acquire ($sem_id)) {
$shm_id = shmop_open(0x4d2, "c", 0666, 200);
if(!$shm_id) {
echo "Impossible de creer la memoire partagee" . "<br />";
// on libère l'accès
sem_remove($sem_id);
exit;
}
.....
Expected result:
----------------
Be able to get back the sem_id of an exiting semaphore
------------------------------------------------------------------------
--
Edit this bug report at https://bugs.php.net/bug.php?id=61608&edit=1