Edit report at https://bugs.php.net/bug.php?id=61608&edit=1
ID: 61608 Comment by: trex_daemon at yahoo 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: Actually I have the same problem. A C process creates the semaphore (with full access: 0666) and then the PHP cannot access the semaphore with the same ID. Is there any news on this ? Previous Comments: ------------------------------------------------------------------------ [2012-04-11 16:26:26] zhanglijiu at gmail dot com 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); } ------------------------------------------------------------------------ [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