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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
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 18:01:29 2024 UTC