php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #61608 sem_get problem
Submitted: 2012-04-03 14:39 UTC Modified: 2012-04-04 15:42 UTC
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:2 of 2 (100.0%)
Same Version:1 (50.0%)
Same OS:1 (50.0%)
From: stephane dot anthoine at gmail dot com Assigned:
Status: Open Package: Semaphore related
PHP Version: 5.4.0 OS: linux 2.6.32
Private report: No CVE-ID: None
View Developer Edit
Welcome! If you don't have a Git account, you can't do anything here.
If you reported this bug, you can edit this bug over here.
(description)
Block user comment
Status: Assign to:
Package:
Bug Type:
Summary:
From: stephane dot anthoine at gmail dot com
New email:
PHP Version: OS:

 

 [2012-04-03 14:39 UTC] 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


Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2012-04-04 15:42 UTC] laruence@php.net
-Package: *General Issues +Package: Semaphore related
 [2012-04-11 16:26 UTC] 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);
}
 [2013-10-03 20:00 UTC] trex_daemon at yahoo dot com
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 ?
 [2013-10-21 11:57 UTC] lenigoor35 at hotmail dot com
See http://www.serverphorums.com/read.php?8,312273 (last post)

Apparently PHP expects the C code to create the semaphore with nsems = 3 as argument. Maybe this solves the problem?
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Nov 21 14:01:29 2024 UTC